0

在 C 中,除了不需要地址运算符的数组之外,还有其他时间吗?例如,我知道这段代码需要操作符的地址:

typedef struct foo_t {
    int bar;
} foo_t;

void foo_init(foo_t *f) { f->bar = 123; }

... {
    foo_t f;

    foo_init(&f);
}

但是这段代码不需要地址操作符:

... {
    char buffer[1024];
    memset(buffer, 0, 1024);
}

这里memset声明为:

void *memset(void *ptr, int value, size_t num);

在 C 中,它会自动将其char[]转换为void*- 但尝试对这样的做同样的foo_t事情:

 foo_t f;
 memset(f, 0, sizeof(foo_t));

不起作用,并且会产生预期的编译时类型错误。与char[]示例一样,如果我们使用数组,它将起作用:

foo_t list[16];
memset(foo, 0, sizeof(list));

它会再次自动foo_t[]void*

这是C语言中唯一一次发生这种类型的转换吗?我怎么知道这些演员何时会发生?

4

3 回答 3

2

我知道的唯一“其他”(见注释)隐式地址获取的情况是函数指针 [ 1 , 2 ]。给定一个函数

int
f(void);

以下两行具有相同的含义。

int (*fptr1)(void) = f;
int (*fptr2)(void) = &f;

makefptr1fptr2函数指针都f分别指向。

于 2015-01-19T02:03:17.553 回答
1

字符串文字通过地址分配给指针,并在用作初始化的 rhs 时通过“值”分配:

const char *str_ptr = "foo";  /* str_ptr points to a string "foo",
                                 in read-only memory. */

char chr_ar[] = "barbar";     /* chr_ar is 7 bytes, and is initialized
                                 with the bytes "barbar" */
于 2015-01-19T02:08:29.867 回答
1

在这个表达式中

char buffer[1024];
memset(buffer, 0, 1024);

数组在传递给时衰减为一个指针memsetmemset在它的第一个参数中需要一个指向可写内存的指针。

这个功能

void foo_init(foo_t *f) 
{ 
    f->bar = 123; 
}

也可以写成

void foo_init(foo_t f) 
{ 
    f.bar = 123; 
}

但是传递的参数将是原始参数的副本,并且更改仅适用于本地副本。

在指针版本中,参数指向结构存储在内存中的位置,因此直接对指针指向的相同数据执行更改。

所以你不需要获取数组的地址,因为它会自动衰减到指向它的第一个元素的指针,当你这样使用时,而当你传递一个分配在堆栈上的对象并且你想改变它时接收者函数,你需要传递一个指向它的指针,你使用操作符的地址。

于 2015-01-19T02:00:02.073 回答