指针
sizeof
- 是一个运算符,给出某个类型或变量在内存中所占据的字节数
- sizeof(int)
- sizeof(double)
- sizeof(i)
一个int占据的是4个字节,一个double占据的是8个字节
取地址符 &
scanf("%d", &i); 里面的&- 获得变量的地址,它的操作数必须是变量
int i ; printf("%x", &i); 获取i的地址,以16进制整数输出 - 地址的大小是否与int相同取决于编译器
int i; printf("%p", &i); 获取i的地址,以地址(32/64位)输出
&不能取的地址
数组的地址
int a[10];
printf("%p\n", &a);
printf("%p\n", a);
printf("%p\n", a[0]);
printf("%p\n", a[1]);
指针变量 *p
int i;
int \*p = &i;
int\* p, q;
int *p, q;
作为参数的指针
void f(int *p); - 在被调用的时候得到了某个变量的地址;
- 在函数里面可以通过这个指针访问外面的这个i
访问某个地址上的变量
- *是一个单目运算符,用来访问指针的值所表示的地址上的变量
- 可以做右值也可以做左值
void f(int *p);
void g(int k);
int main(void)
{
int i = 6;
printf("&i=%p\n", &i);
f(&i);
g(i);
return 0;
}
void f(int *p)
{
printf("p=%p\n",p);
printf("*p=%d\n", *p);
*p = 26;
}
void g(int k)
{
printf("k=%d\n",k);
}
传入地址 为什么int i; scanf("%d",i); 编译没有报错?
因为scanf会把i单做一个地址,它访问的是地址为i的内存单元。
传入函数的数组成了什么?
- 函数参数表中的数组实际上是指针
sizeof(a) == sizeof(int*) - 但是可以用数组的运算符[]进行运算
因此以下四种函数原型是等价的
int sum(int *ar, int n); int sum(int *, int); int sum(int ar[], int n); int sum(int [], int);
数组变量是特殊的指针
指针初始化 在学习过程中,我发现一个问题
int *p = &i; //可编译,并且让指针p指向i所在单元
int *p;
int i;
*p = i; //编译报错
疑问 *p 是一个地址所指向的内容,&i是i这个变量所在的地址,这两个不同的东西怎么能做赋值?我的理解 我的理解是:定义一个指针后必须进行初始化。初始定义指针变量的时候既要定义数据类型,要给他定义这个指针指在哪里,直接融在一起了。就成了int *p=&i。实际上应该拆成定义一个指针 int *p,这个指针是i所在的地址即p=&i。看了一些大佬的博客 关于int*p=&a与int p;p=&a;与p = a;与&p的解惑 根据大佬的博客,知道了指针初始化可以分为2种
- 定义时直接初始化
- 定义之后进行初始化
若在定义之后,没有初始化,对指针赋值,编译器会报错。由于int *p后,p指向的是一个随机的地址,那么这个地址上储存的值也是随机的,我们不能随意修改其值。否则有可能会造成系统紊乱。
字符
字符类型
char 是一种整数,也是一种特殊的类型:字符。- 用单引号表示的字符字面量:
'a' , '1' '' 也是一个字符- printf和scanf里用
%c 来输入输出字符
逃逸字符
- 用来表达无法印出来的控制字符或特殊字符,它由一个反斜杠“\”开头,后面跟上另一个字符,这两个字符合起来,组成了一个字符
printf("请分别输入身高的英尺和英寸,如输入\"5 7\"表示5英寸和7英寸:");
逃逸字符表
字符 | 意义 |
---|
\b | 回退一格 | \t | 到下一个表格位 | \n | 换行 | \r | 回车 | \" | 双引号 | ’ | 单引号 | \ | 反斜杠本身 |
回退:让下一个输出回到\b前一个的前面一个位置上去。如果不输出东西,结果不会影响;如果输出东西,\b之前输出的前一个会被盖掉。
shell 我们写的程序运行的时候有一个黑色的窗口,这个窗口也是别人写的程序,我们通常叫做shell。 不同的shell会对不同的控制字符做出特殊的反应。
字符串
字符串 字符串是一个字符数组。 “Hello”会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0。
- 字符串以数组的形式存在,以数组或指针的形式访问
- 更多的是以指针的形式
string.h 里有很多处理字符串的函数
字符数组 char word[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘!’, ‘\0’ }; 6个字符,数组总共由7个单元。
-
以0(整数0)结尾的字符串 -
0 和'\0' 是一样的,但是和’0‘ 不同 -
0标志字符串的结束,但它不是字符串的一部分 -
计算字符串长度的时候不包含这个0 -
C语言的字符串是以字符数组的形态存在的
- 不能通过运算符对字符串做运算
- 可以通过数组的方式遍历字符串
- 唯一特殊的地方是字符串字面量可以用来初始化字符数组
字符串常量
- “Hello”
- "Hello"会被编译器变成一个字符数组放在某处,这个数组的长度是6,还有表示结束的0
- 两个相邻的字符串常量会被自动连接起来
字符串变量 char *str = “Hello”; char word[] = “Hello”; char line[10] = “Hello”;
char* s = “Hello, world!”; s是一个指针,初始化为指向一个字符串常量 由于这个常量所在的地方,所以实际上s是const char * s, 但是由于历史的原因,编译器接受不带cosnt的写法 但是试图对s所指的字符串做写入会导致严重的后果 如果需要修改字符串,应该用数组: char s[] = “Hello, world!”;
指针还是数组?
- char *str = “Hello”;
- 指针:这个字符串不知道在哪里
- char word[] = “Hello”;
- 数组:这个字符串在这里
- 如果要构造一个字符串 ——>数组
- 如果要处理一个字符串 ——>指针
*char 是字符串吗?
- 字符串可以表达为char *的形式
- char*不一定是字符串
- 本意是指向字符的指针,可能指向的是字符的数组(就像int*一样)
- 只有它所指的字符数组有结尾的0,才能说它所指的是字符串
字符串计算
字符串赋值
- char *t = “title”;
- char *s;
- s = t;
- 并没有产生新的字符串,只是让指针s指向了t所指的字符串,对s的任何操作就是对t做的
字符串输入输出
- char string[8];
- scanf("%s",string);
- printf("%s",string);
写两个程序来测试一下
#include<stdio.h>
int main()
{
char word[8];
scanf("%s", word);
printf("%s##", word);
return 0;
}
在这个程序中,输入“Hello world!”,输出的结果只有Hello 。原因是scanf读一个字符串,只能读到空格或者回车为止。
#include<stdio.h>
int main()
{
char word[8];
char word2[8];
scanf("%s", word);
scanf("%s", word2);
printf("%s##%s##", word, word2);
return 0;
}
在这个程序中,输入“Hello world!”,输出的结果是:Hello##world!## ,即在word输入的是“Hello”,在word2种输入的是“world!”。
- scanf读入一个单词(到空格、tab或回车为止)
- scanf是不安全的,因为不知道读入的内容的长度
为了使scanf读入的内容放在字符数组中不越界,可以在%后加入要读入的字符数。如scanf("%7s", word); 表示最多读入7个字符,小于7个字符是可以的。
#include<stdio.h>
int main()
{
char word[8];
char word2[8];
scanf("%7s", word);
scanf("%7s", word2);
printf("%s##%s##", word, word2);
return 0;
}
- 若输入
123 12345678 ,输出结果为123##1234567## ; - 若输入
12345678 ,输出结果为1234567##8## ;
- 在%和s之间的数字表示最多允许读入的字符的数量,这个数字应该比数组的大小小1
空字符串
- char buffer[100] = “”;
- 这是一个空的字符串,buffer[0] = = ‘\0’
- char buffer[] = “”;
-这个数组的长度只有1!
字符串函数
strlen
- size_t strlen(const char *s);
- 返回s的字符串长度(不包括结尾的0)
strcmp
- int strcmp(const char *s1, const char *s2);
- 比较两个字符串,返回:
- 0:s1 == s2
- 1:s1 > s2
- -1:s1 < s2
|