【问题标题】:Why does memset work differently in functions?为什么 memset 在功能上的工作方式不同?
【发布时间】:2020-02-18 02:27:00
【问题描述】:

我试图弄清楚为什么当我从函数内部调用 memset 时它不起作用。 当然,我可以使用 for 循环来重置所有值,但我是来学习的,这件事让我无法解释。

/* First source code */
#include <stdio.h>
#include <string.h>

int main(void) {
    int i, j, num;

    printf("Digit a number :");
    scanf("%d", &num);

    int magic[num][num];

    printf("First\n");
    for(i = 0; i < num; ++i) {
        for(j = 0; j < num; ++j) {
            printf("%4d", magic[i][j]);
        }
        printf("\n\n");
    }

    memset(magic, 0, sizeof(magic));

    printf("Before\n");
    for(i = 0; i < num; ++i) {
        for(j = 0; j < num; ++j) {
            printf("%4d", magic[i][j]);
        }
        printf("\n\n");
    }

    return 0;
}

/* Second source code */
#include <stdio.h>
#include <string.h>

void create_magic_square(int n, int magic_square[][n]);
void print_magic_square(int n, int magic_square[][n]);

int main(void) {
    int num;
    printf("Digit a number :");
    scanf("%d", &num);
    int magic[num][num];
    create_magic_square(num, magic);
    return 0;
}

void create_magic_square(int n, int magic_square[][n]) {
    int i, j;

    printf("First\n");
    for(i = 0; i < n; ++i) {
        for(j = 0; j < n; ++j) {
            printf("%4d", magic_square[i][j]);
        }
        printf("\n\n");
    }

    //memset(magic_square, 0, n * sizeof(magic_square[0]));
    memset(magic_square, 0, sizeof(magic_square));

    printf("Before\n");
    for(i = 0; i < n; ++i) {
        for(j = 0; j < n; ++j) {
            printf("%4d", magic_square[i][j]);
        }
        printf("\n\n");
    }
}

在第二个代码(带有函数)中,我应该输入以下代码: memset (magic_square, 0, n * sizeof (magic_square [0])); 用于清除二维数组,同时: memset (magic_square, 0, sizeof (magic_square)); 不起作用。为什么会这样?

【问题讨论】:

  • 打印sizeof的结果,你大概看看指针的大小吧!

标签: c arrays function c99 memset


【解决方案1】:

当您将数组传递给 C 中的函数时,它们会衰减为指向数组中第一个元素的指针,即使您在函数原型中指定了数组类型 (a)。因此,sizeof 将为您提供 指针的大小, 而不是数组的大小。

通常的做法是将数组大小与数组一起传递(可能是size_t)并使用那个来编织你的魔法,例如:

int zeroArray(void *address, size_t sz) { // void* makes it clear
    memset(address, 0, sz);               // but int thing[][] would be same.
}
:
int xyzzy[42][7];
zeroArray(xyzzy, sizeof(xyzzy));

但是,您已经向当前函数传递了足够的信息来执行此操作,特别是 n。您应该能够只使用它来形成 sizeof 运算符的类型(可以采用变量 类型),它会满足您的需要:

memset(magic_square, 0, sizeof(int[n][n]));

(a) 涵盖在最新标准C11 下的6.3.2.1 Lvalues, arrays, and function designators /3 部分:

除非它是sizeof 运算符、_Alignof 运算符或一元&amp; 运算符的操作数,或者是用于初始化数组的字符串字面量,否则表达式类型为“array of type " 转换为类型为 "pointer to type" 的表达式,它指向数组对象的初始元素,并且不是左值。

尽管有c99 标记,我还是引用了标准的最新 迭代,唯一的区别是C99 标准没有提及Alignof,因为它在该迭代中不存在。除此之外,报价是相同的。

这可以追溯到,甚至可以追溯到 K&R 第一版,5.3 Pointers and arrays

实际上,对数组的引用被编译器转换为指向数组开头的指针。

【讨论】:

    猜你喜欢
    • 2019-08-18
    • 1970-01-01
    • 2022-11-03
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多