【问题标题】:Value stored in a Pointer to an uninitialized array is not NULL?存储在指向未初始化数组的指针中的值不为 NULL?
【发布时间】:2021-08-09 09:19:09
【问题描述】:

我总是得到下面程序的输出为“b is not NULL”。当我尝试打印 a 或 b 的值时,它们绝对是空白的。知道为什么会这样吗?

#include <stdio.h>
int main()
{
    char a[10];
    char *b = a;

    if(b == NULL) 
      printf("b is NULL");
    else
      printf("b is not NULL");
      
    return 0;
}

【问题讨论】:

  • 你能更精确一点吗? “绝对空白”是什么意思?在您的代码中,b 将是数组的地址(该值可能看起来很奇怪,但不会为零);如果您打印a 的任何元素,它们将具有未定义的值(因为您没有给它们任何值)。
  • b 包含a 的地址(更准确地说,是a 的第一个元素的地址)。它永远不会是NULL,因为a 显然有一个非NULL 地址。至于打印a 的值,您需要先将它们设置为某个值,然后才能有意义地打印它们。否则,您将打印未定义的值。
  • 真正的问题是你为什么认为它会是 NULL?

标签: arrays c pointers implicit-conversion


【解决方案1】:
char a[10];
char *b = a;

指向未定义数组的指针中存储的值不为 NULL?

  1. 数组a 定义得很好。它是not initialized,并且数组的元素尚未确定值。因此,当您打印数组a 的元素时,可以输出任何值。阅读undefined behaviour

  2. 指针b 没有“存储”任何值。它存储对具有char 类型的对象的引用。该对象可以“存储”一个 char 值,但不能“存储”指针本身。

  3. 由于数组a 定义明确并驻留在内存中,因此对其第一个元素的引用(如a decays 指向该数组第一个元素的指针)不能是NULL。

我认为你需要阅读你最喜欢的C book的指针章节。

【讨论】:

  • 所以,如果我打印指针 b,比如 printf("%s", b);它应该给我一些垃圾而不是 NULL 对吗?
  • 在这种情况下从不为 NULL。 NULL 是一个特殊的不存在的引用。使用未初始化的自动变量是 UB。你不知道会发生什么。
  • @KarthikGottipalli 您可以使用printf("%p\n", (void *)b); 打印指针b。这将打印实际的指针值,而不是指针指向的垃圾字符串内容。
  • @KarthikGottipalli 你可能对空指针和空终止字符串之间的区别感到困惑。
【解决方案2】:

指向未定义数组的指针中存储的值不为 NULL?

指针值是数组的地址,不管它(数组)是否已经赋值,所以不,它不会是NULL。


总是得到下面程序的输出为“b is not NULL”。当我尝试打印a 或b 的值时,它们绝对是空白的。知道为什么会这样吗?

打印指针值的说明符是%p。

Live demo

char a[10];
char *b = a;
printf("\n%p", (void*)b);
printf("\n%p", (void*)a);

输出应该是这样的:

0x7ffec02d3d16
0x7ffec02d3d16

因此,如您所见,指针值不是 NULL,而是数组的地址。

另一方面,如果您将 char 数组作为字符串打印,即:

printf("\n%s", b);
printf("\n%s", a);

你的程序有未定义的行为,它可能什么也不打印,它可能会打印一些与 garbage 数据对应的随机字符,这些数据存储在声明的数组现在占用的内存位置,这些是最常见的结果,但由于没有要求表现出不安全行为的程序应该做什么,因此您可以期待各种奇怪的结果。

【讨论】:

  • @0___________ 啊,是的,很好发现,顺便说一句,答案很好。
【解决方案3】:

指针b 具有有效值。它指向数组 a 的第一个元素。

char a[10];
char *b = a;

所以它不能等于NULL。

另一方面,具有自动存储持续时间的数组a 未初始化。它的元素具有不确定的值。

如果您将使用字符串或字符序列初始化数组,则可以使用指针b 输出它们。

例如

char a[10] = "Hello";
char *b = a;

puts( b );

或

char a[10] = "0123456789";
char *b = a;

printf( "%.*s\n", ( int )sizeof( a ), b );

如果你想输出存储在指针 b 中的值,即数组 a 的第一个元素的地址,你可以写例如

printf( "b = %p\n", ( void * )b );

输出的值将与printf的调用中的相同

printf( "a = %p\n", ( void * )a );

你可以编写如下的测试程序。

#include <stdio.h>

int main(void) 
{
    char a[10];
    char *b = a;
    
    if ( b == a )
    {
        puts( "b is equal to the address of the first element of a" );
    }
    
    return 0;
}

它的输出将是

b is equal to the address of the first element of a

【讨论】:

    猜你喜欢
    • 2010-10-11
    • 2016-03-26
    • 1970-01-01
    • 2022-08-15
    • 2015-04-28
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多