场景1
int *nums = {5, 2, 1, 4};
printf("%d\n", nums[0]);
为什么会出现这一段错误?
您声明nums
了一个指向int的指针-nums
应该在内存中保存一个整数的地址。
然后,您尝试初始化nums
为多个值的数组。因此,在不深入研究细节的情况下,这在概念上是不正确的-将多个值分配给应该保存一个值的变量是没有意义的。在这方面,如果您这样做,将会看到完全相同的效果:
int nums = {5, 2, 1, 4};
printf("%d\n", nums);
在任何一种情况下(将多个值分配给一个指针或一个int变量),然后发生的事情是该变量将获得第一个值5
,而其余的值将被忽略。这段代码符合要求,但是您会为分配中不应包含的每个其他值收到警告:
warning: excess elements in scalar initializer
。
对于为指针变量分配多个值的情况,在访问时程序会出现段错误nums[0]
,这意味着您将按原义推迟地址5中存储的任何内容。nums
在这种情况下,您没有为指针分配任何有效的内存。
值得注意的是,为int变量分配多个值的情况下没有段错误(您在这里没有引用任何无效的指针)。
场景2
int nums[] = {5, 2, 1, 4};
这不会发生段错误,因为您正在合法地在堆栈中分配4个int数组。
场景3
int *nums = {5, 2, 1, 4};
printf("%d\n", nums);
这不会像预期的那样发生段错误,因为您正在打印指针本身的值,而不是指针所引用的值(这是无效的内存访问)。
其他
每当您像这样对指针的值进行硬编码时,几乎总是注定会出现段错误(因为确定任务是哪个进程可以访问哪个内存位置是操作系统的任务)。
int *nums = 5;
因此,经验法则是始终初始化一个指向某些已分配变量地址的指针,例如:
int a;
int *nums = &a;
要么,
int a[] = {5, 2, 1, 4};
int *nums = a;