- 首先,还是从hello world开始。
#include <stdio.h>
int main(void) {
printf("Hello Worldn");
return 0;
}
针对这个程序,要理解#include的功能。为什么要使用#include呢?stdio.h是什么?
stdio.h是standard input and output。这里因为我们使用了printf库函数,这个函数不是我们自己实现的,为了使用它,必须要在我们自己的代码中包括实现printf的代码。#include<stdio.h>的作用就是找到系统中相应的代码,并且将其加入我们的代码。
问题:系统中的stdio.h在哪里?
2. C语言中的字符串
C语言中的字符串表示为内存中的字符。字符串的结尾包括NULL(0)字节。所以,“ABC”需要4个字节保存,['A','B','C','0']。确定C语言中字符串的长度的唯一的方法是一直读取内存,直到发现一个NULL字节。每个字符总是一个字节。
![620c4907aa518b726e3fa631c20d75d2.png](https://i-blog.csdnimg.cn/blog_migrate/d84604f2bbc87f771a78c080f5691224.jpeg)
以上代码中,会出现字符串被截断的情况:
![6eb795b4e6ecf71e84b38525974b3dc2.png](https://i-blog.csdnimg.cn/blog_migrate/1b5acd4da89a3ee5942901611253348c.jpeg)
当在代码中写入字符串常量“ABC”,则该字符串常量被计算为一个字符指针(char *),其指向字符串的第一个字节。也即,下面代码中的指针ptr将会保存字符串“ABC”的第一个字符的地址。
char *ptr = "ABC"
初始化字符串的方法包括如下:
char *str = "ABC";
char str[] = "ABC";
char str[]={'A','B','C','0'};
数组和指针的区别后面还会讨论。
3. 如何声明指针?
一个指针指向一个地址。指针的类型很有用(很重要,它告诉编译器使用该指针时,每次需要读多少字节),可以如下声明指针:
int *ptr1;
char *ptr2;
在C的语法中, int * 不应该理解成 (int *),而是int (*ptr)。 所以,下面的定义中,
int* ptr3, ptr4;
只有ptr3被声明成了指针,ptr4还是普通的int变量。如果需要声明两个int型指针,则需要如下声明:
int *ptr3, *ptr4;
4. 如何使用指针读/写内存?
假设声明了一个指针 int *ptr。假设ptr指向的地址是0x1000(32位地址和64位地址,实际上是),如果我们想利用这个指针进行写入操作,那么可以解引用:
*ptr = 0; // Writes some memory.
C编译器会检查 ptr 是int型的指针,并且要写入 sizeof(int)个相邻的字节,从指针所指的起始位置开始。譬如,在以上的例子中,将会写入0x1000,0x1001,0x1002,0x1003四个字节,这四个字节的值都为0。对基础数据类型,这都一样,对结构体则稍微复杂一些。
5. 指针运算
对指针可以进行运算,譬如可以对指针进行加减操作。 但是,加减操作的含义需要认真思考,因为加减操作的单位依赖于指针的类型。对于 char 指针,比较简单,因为它的单位是一个字节:
char *ptr = "Hello"; // ptr 保持 'H'的内存位置
ptr += 2; //ptr 现在指向第一个'l'
但是如果指针是多字节的其他类型,那么操作就复杂了:
char *ptr = "ABCDEFGH"; // ptr是char类型的指针
int *bna = (int *) ptr; // bna是 int型的指针,同样指向上面字符串的位置
bna +=1; // 对bna加1;这里,因为bna是int型,所以 +1 实际上是 增加了4个字节
ptr = (char *) bna; //将ptr指向 bna 现在指向的位置
printf("%s", ptr); //此时打印,只会打印出EFGH,因为一个字符只占一个字节,而bna向前走了4个字节
return 0;