该程序不会更改该阵列的“基地址”。它甚至没有尝试。
你传递给fn的是内存中256个字符块的地址。它在数字上与str
在其他表达式中衰减的指针相同,只是不同的类型。在这里,数组真的保持一个数组 - 将地址运算符应用到数组是数组不会衰减到指针的一个实例。例如,增量&str
会使其数值增加256.这对于多维数组非常重要,正如我们所知,它实际上是C中的一维数组阵列。增加“二维”数组的第一个索引必须将地址提前到下一个“块”或“行”的开始处。
现在赶上。就fn而言,您通过的地址指向包含另一地址的位置。那是不正确的;它指向一系列字符。打印该字节序列解释为指针会显示'A'字节值,即65或0x41。然而,fn认为指向的内存包含一个地址,并用“kj”驻留在内存中的地址覆盖它。由于在str中分配了足够的内存来保存地址,因此分配成功并在该位置生成可用地址。
应该指出,这当然不能保证工作。导致失败的最常见原因应该是对齐问题 - 我认为str
不需要为指针值正确对齐。标准规定函数参数必须与参数声明兼容。任意指针类型不能分配给对方(需要通过void指针或者强制转换)。
编辑: david.pfx指出(即使有适当的转换),代码调用未定义的行为。该标准要求通过最新公共草案第6.5/7节中兼容的左值(包括引用的指针)来访问对象。当正确编译和编译gcc -fstrict-aliasing -Wstrict-aliasing=2 ...
gcc警告“类型双关”。理由是编译器应该自由地假设不兼容的指针不会修改相同的内存区域;这里不需要假定fn改变str的内容。这使得编译器能够优化不必要的重新加载(例如从内存到注册)。这将对优化起作用;一个调试会话将无法重现错误的可能示例(即,如果正在调试的程序将被编译而不进行用于调试目的的优化)。话虽如此,如果一个非优化编译器会在这里产生意想不到的结果,我会感到惊讶,所以我让剩下的答案保持原样。 -
我插入了一些debug printfs来说明发生了什么。现场可以看到一个实例:http://ideone.com/aL407L。
#include<stdio.h>
#include<string.h>
static char* abc = "kj";
// Helper function to print the first bytes a char pointer points to
void printBytes(const char *const caption, const char *const ptr)
{
int i=0;
printf("%s: {", caption);
for(i=0; i<sizeof(char *)-1; ++i)
{
printf("0x%x,", ptr[i]);
}
printf("0x%x ...}\n", ptr[sizeof(char *)-1]);
}
// What exactly does this function do?
void fn(char**s) {
printf("Inside fn: Argument value is %p\n", s);
printBytes("Inside fn: Bytes at address above are", (char *)s);
// This throws. *s is not a valid address.
// printf("contents: ->%s<-\n", *s);
*s = abc;
printf("Inside fn: Bytes at address above after assignment\n");
printBytes(" (should be address of \"kj\")", (char *)s);
// Now *s holds a valid address (that of "kj").
printf("Inside fn: Printing *s as string (should be kj): ->%s<-\n", *s);
}
int main() {
char str[256];
printf("size of ptr: %zu\n", sizeof(void *));
strcpy(str, "AAAAAAAA"); // 9 defined bytes
printf("addr of \"kj\": %p\n", abc);
printf("str addr: %p (%p)\n", &str, str);
printBytes("str contents before fn", str);
printf("------------------------------\n");
// Paramter type does not match! Illegal code
// (6.5.16.1 of the latest public draft; incompatible
// types for assignment).
fn(&str);
printf("------------------------------\n");
printBytes("str contents after fn (i.e. abc -- note byte order!): ", str);
printf("str addr after fn -- still the same! --: %p (%p)\n", &str, str);
return 0;
}
为后人,[这里](http://stackoverflow.com/questions/25660493/assigning-to-a-char-array-using-assignment-operator-and-double-pointers)是删除的问题 – 2014-09-04 11:34:36