序言
继续总结C语言中的一些细枝末节的知识点,厘清不熟悉的地方。
本文主要内容:
C语言中0和NULL的区别
结构体初始化取值问题
1. C语言中0和NULL的区别
0作为一个整数,是一个数值,可以是整型int,字符型char,长整型long等等。
0作为一个指针,是一个空指针常量。(i.e. 指针内容全为0,0x00000000),常见的 0、‘\0’、0L、3 - 3、0 * 17等都是空指针常量。
- ’\0’字符串结束符,用在字符串的末尾,不是指针,也不是普通的数值
- ’\0’字符串结束符,用在字符串的末尾,不是指针,也不是普通的数值
什么是空指针:指针通过空指针常量赋值之后就是一个空指针,不指向任何实际的对象或者函数。
什么是NULL:在C语言 stdio.h / stddef.h中有如下定义
- NULL是一个标准规定的宏定义,用来表示空指针常量
#define NULL ((void *)0)
NULL和0:
在C语言中,可以说NULL就是0,两者是完全等价的。只不过NULL用在指针和对象,0多用于数值。
NULL的值(i.e. NULL指向了内存中的什么地方):
取决于系统的实现,对于大多数系统(某些系统中NULL和0的值不同)来说,一般指向0地址,即空指针的内部全用0来表示,64位机下0x00000000。
指针初始化为NULL,指向一个无意义地址,实际上是指向了0x00000000。
2. 结构体初始化
(1) 结构体元素通过以下方式初始化后每一个元素的取值为多少?
- [1] 结构体指针元素 - 未分配空间
现有结构体
structure node
{
int data;
struct node* next;
};
则通过下列方式初始化之后
struct node* newNode = NULL;
每个元素的取值为多少?
答:
- 在程序中,node结构体的代码段,如果不主动分配空间,编译器不会为其分配空间的。
- 这样,当声明了newNode结构体之后,newNode = NULL只表示该指针指向NULL,不指向内存中的任意地址,不涉及其中具体取值。
- [2] 结构体指针元素 - 分配空间
初始化方式1:
struct node* newNode;
newNode = (struct node *)malloc(sizeof(struct node));
memset(newNode, 0, sizeof(struct node));
每个元素的取值为多少?
答
分配空间之后进行如上的memset()初始化,表示
newNode -> data = 0;
newNode -> next = 0 或者说 NULL;对于大多数系统,使用memset()来得到空指针和 *pointer = NULL 方式是等价的,但有的系统memset(p, 0, sizeof(p))时会在pointer中存着“非零空指针”。所以可用如下方式初始化
初始化方式2:
struct node* newNode;
newNode = (struct node *)malloc(sizeof(struct node));
newNode -> data = 0;
newNode -> next = NULL;
结论:
指针初始化时,采用 pointer = NULL 和 pointer = 0 都是可以的。
在C语言中,采用 memset() 和 元素分别赋值初始化 都是可以的,没有区别。
3. NULL和0的区别以及结构体指针初始化验证示例
- 代码(C)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct test
{
int data;
struct test *next;
int data1;
struct test *prev;
};
int main()
{
//有符号和无符号数
int a = 1;
char b = (0 - 1);
unsigned char c = (0 - 1);
printf("%d\n", b);
printf("%u\n", c);
//NULL和0的比较
int *p1 = NULL, *p2 = 0, *p3 = &a;
int *p4 = (int *)malloc(sizeof(int));
memset(p4, 0, sizeof(int));
//结构体初始化
struct test *p5 = (struct test *)malloc(sizeof(struct test));
memset(p5, 0, sizeof(struct test));
struct test *p6 = (struct test *)malloc(sizeof(struct test));
p6->data = 0;
p6->next = NULL;
printf("%d\n", sizeof(struct test));
printf("%d\n", p5->data);
printf("%d\n", p6->data);
printf("0x%p 0x%p 0x%p 0x%p 0x%p 0x%p\n", p1, p2, p3, p4, p5->next, p6->next);
return 0;
}
- 输出
-1 【有符号数,0 - 1为 -1】 |
255 【无符号数8bit数,0 - 1为 11111111 = 255】 |
24 【第一个struct test *next以int data为准对齐,第二个struct test *prev以double data1对齐,整个结构体大小为最大元素double data1大小整数倍】 |
0 【用memset()初始化为0】 |
0 【直接赋值初始化为0】 |
0x00000000 【*p1 = NULL,其值为0x00000000,即NULL的地址为0x00000000】 |
0x00000000 【*p2 = 0,其值也为0x00000000,即0的地址为0x00000000】 |
0x0028FF00 【*p3 = &a,即变量a的地址为0x0028FF00】 |
0x00031080 【*p4 = 结构体地址,程序每次执行都会变】 |
0x00000000 【p5 -> next,使用memset()将结构体指针初始化为空指针】 |
0x00000000 【p6 -> next,使用直接赋值将结构体指针初始化为空指针】 |
http://www.cnblogs.com/youxin/archive/2012/03/27/2420023.html
2017.08.27