sizeof
1、是一个运算符,给出某个类型或变量在内存中所占据的字节数
2、sizeof(int)
3、Sizeof(i)
1、scanf(“%d, &i);里的&
2、获取表量的地址,它的操作数必须是变量
int i; printf(“%x, &i);
3、地址的大小是否与int相同取决于编译器
Int i;printf(“%p, &i);
&不能取的地址
&不能对没有地址的东西取地址
&(a+b)?
&(a++)?
&(++a)?
&a=a=a[0]
相邻地址的差距是4
如果能够将取得的变量的地址传递给一个函数,能否通过在这个地址在那个函数访问这个变量?
scanf(“%d”, &i)
scanf()的原型应该是怎样的?我们需要一个参数保存别的变量的地址,如何表达能够保存地址的变量?
指针,就是保存地址的变量
int i;
Int* p = &i;
Int* p,q;
Int *p,q;
1、变量的值是内存的地址
2、普通变量的值是实际的值
3、指针变量的值是具有实际值的变量的地址
作为参数的指针
1、void f(int *p);
在被调用的时候得到了某个变量的地址;
2、int i=0; f(&i);
在函数里面可以通过这个指针访问外面这个i
访问地址那个变量*
*是一个单目运算符,用来访问指针的值所表示的地址上的变量
可以做右值也可以做左值
int = *p;
*p = k+1;
传入地址
Int i; scanf(“%d”,i);
编译不报错,运行一定出错
int isPrime(int x, int knownPrimes[], int numberOfknownPrimes)
{
int ret = 1;
int i;
for ( i=1; i<numberOfknownPrimes; i++) {
if ( x% knownPrimes[i] == 0 ) {
ret = 0;
break;
}
}
return ret;
}
函数参数表中的数组实际上是指针;
sizeof(a) == sizeof(int*)
但是可以用数组的运算符][]进行运算
以下四种函数原型是等价的
int sum(int *ar, int n);
int sum(int *, int);
Int sum(int ar[], int n)
Int sum(int [], int);
数组变量是特殊的指针
1、数组变量本身表达地址;
int a[10]; int*p=a; // 无需用&取地址
但是数组的单元表达的是变量,需要用&取地址
a==&a[0]
2、[]运算符可以对数组做,也可以对指针做
P[0] 等价 a[0]
3、*运算符可以对指针做也可以对数组做
4、数组变量是const的指针,所以不能被赋值
int a[] 等价 *const a=…
char是一种整数,也是一种特殊的类型:字符。这是因为:
1、用单引号表示的字符字面量:’a’, ‘1’
2、“也是一个字符
3、printf和scanf里用%c来输入输出字符
将’1‘输入
scanf(“%c”, &c);–>1
Scanf(“%d”, &i); c=i; -->49
‘1’的ASCII编码是49,所以当c==49是,它代表’1‘
Printf(“%i %c\n”, c,c );
一个49的各自表述!
scanf(“%d %c”, &i, &c);
scanf(“%d%c”, &i, &c);
二者不同
大小写转换
字母在ASCII表中是顺序排列的
大写字母和小写字母是分开排列的,并不是在一起
\b 回退一格 \t 到下一个表格位
\n 换行 \r 回车 \”双引号
\’ 单引号 \ 反斜杠本身
逃逸字符
用来表达无法印出来的控制字符或特殊,它由反斜杠“\”,后面跟上另一个字符,这两个字符合起来,组成一个字符
char word[] = {‘H’, ‘e’, ‘I’, ‘I’, ‘O’, ‘!’}; //不是字符串
word[0] H
word[1] e
word[2] I
word[3] I
word[4] o
word[5] !
char word[] = {‘H’, ‘e’, ‘I’, ‘I’, ‘O’, ‘!’, ‘\0’}; //是字符串
word[0] H
word[1] e
word[2] I
word[3] I
word[4] o
word[5] !
word[6] \0
1、以0(整数0)结尾的一串字符
0或‘\0’是一样的,但是和’0’不同
2、0标志字符串的结束,但他不是字符串的一部分
计算字符串长度的时候不包含这个0
2、字符串以数组的形式存在,以数组或指针的形式访问更多的是指针的形式
3、String,h里有很多处理字符串的函数
字符串
1、C语言的字符串是以字符数组的形态存在的
2、不能用运算符对字符串做运算
3、通过数组的方式可以遍历字符串
4、唯一特殊的地方是字符串字面量可以用来初始化字符数组
以及标准库提供了一系列字符串的函数
字符串变量
“hello”会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0
两个相邻的字符常量会被自动连接起来
字符串常量
char* s = “Hello, world!”;
·s是一个指针,初始化为指向一个字符串常量
由于这个常量所在的地方,所以实际上s是const char* s,但是由于历史的原因,编译器接受不带const的写法
但是试图对s所指的字符做写入会导致严重的后果
如果需要修改字符串,应该用数组:
char s[] = “Hello, world!”;
如果要构造一个字符串–>数组
如果要处理一个字符串–>指针
char *str = “Hello”;
char word[] = “Hello”;
数组:这个字符串在这里
作为本地变量空间自动被回收
指针:这个字符串不知道在哪里
处理参数
动态分配空间
字符串可以表达为char的形式
char不一定是字符串
本意是指向字符的指针,可能指向的是字符的数组(就像int*一样)
只有它所指的字符数组有结尾的0,才能说它所指的是字符串
char *t = “title”
char *s;
s=t;
并没有产生新的字符串,只是让指针s指向了所指的字符串,对s的任意操作就是对t做的
char string[8];
scanf(“%s”, string);
printf(“%s”, string);
scanf读入一个单词(到空格、tab或回车为止)
scanf是不安全的,因为不知道要读出的内容的长度
安全的输入
char string[8];
scanf(“%7s”, string);
在%和之间的数字表示允许读入的数量,这个数字应该比数组的大小小一
常见错误
char string
scanf(“%s”, string);
以为char是字符串类型,定义了一个字符串类型string就可以直接使用了
由于没有对string初始化为0,所以不一定每次运行都出错
空字符串
char buffer[100]=” “;
只是一个空字符串,buffer[0] == ‘\0’
char buffer[] = “ “;
这个数组的长度只有1!
给一个指针加1表示让指针指向下一个变量
int a[10];
int *p = a;
*(p+1)< -->a[1]
如果指针不是指向一篇连续分配的空间,如果数组,则这种运算没有意义
这些算术运算可以对指针做;
给指针加、减一个整数(+,+=,-,-=)
递增递减(++/–)
两个指针相减(sizeof的量)
*p++
取出p所指的那个数据来,完事后顺便把p移到下一个位置去
*
的优先级虽然高,但是没有++高
常用于数组类的连续空间操作
某些CPU上,可以直接被翻译成一条汇编指令
遍历数组
for( p=ac; *p!=-1;p++) {
while ( *p != -1 ) {
printf(“%d\n”, *p++);
}
<,<=,==,>,>=,!= 都可以对指针做
比较他们在内存中的地址
数组中的单元的地址肯定是线性递增的
当然你的内存中也有0地址,但是0地址通常是个不能随意碰的地址
所以指针不应该具有0值
因此可以用0地址来用表示特殊的事情
返回的指针是无效的
指针没有被真正初始化(先初始化为0)
NULL是一个预定定义的符号,表示0地址
有的编译器不愿意用0来表示0地址
指针的类型
无论指向什么类型,所有的指针的大小都是一样的,因为都是地址
但是指向不同类型的指针是不能相互赋值的
这是为了避免用错指针
指针的类型转换
void表示不知道指向什么东西的指针
计算时与char相同(但不相通)
指针也可以转换类型
int p = &i; voidq = (void*)p;
这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量
用指针来做什么
需要传入较大的数据时用作参数
传入数组后对数组做操作
函数返回不止一个结果
需要用函数来修改不止一个变量
动态申请的内存…
size_t strlen(const char *s);
返回s的字符串长度(不包括结尾的0)
#include
#include
size_t mylen(const char* s)
{
int cnt = 0;
int idx = 0;
while(s[idx] != '\0') {
idx++;
cnt++;
}
return cnt;
}
int main(int argc, char const *argv[])
{
char line[] = "hello";
printf("strlen=%lu\n", mylen(line));
printf("sizeof=%lu\n", sizeof(line));
return 0;
}
strcmp
int strcmp(const char *s1, const char *s2);
比较两个字符串,返回: strcpy strcat strchr 返回NULL表示没有找到 strstr //寻找字符串 该函数返回 str 中最后一次出现字符 c 的位置。如果未找到该值,则函数返回一个空指针。 strcasestr //寻找单个字符 忽略大小写 tips:
0:s1 == s2
1:s1>s2
-1:s1#include
三、strcpy和strcat
char* strcpy(char *restrict dst, const char *restrict src);
把src的字符串拷贝到dst
restrict表明src和dst不重叠(C99)
返回dst
为了能链接起代码来
先是目的后是元
复制一个字符串 char *dst = (char*)malloc(strlen(src)+1);
strcpy(dst, src);
#include
charstrcat(charrestrict s1,const char *resrict s2);
把s2拷贝到s1的后面,结成一个长长的字符串
返回s1
s1必须有足够的空间
tip:strcpy和strcat都可能出现安全问题(即,字符串容量问题)char* strncpy(char *restrict dst, const char *restrict src, size_t n);
char* strncat(char*restrict s1, const char *restrict s2, size_t n);
int strncmp(const char *s1, const *s2, size_t n);
四、strchr
char*strchr(const char*s, int c); //从左
char*strrch(const char*s, int c); //从右
#include
五、strstr和strcasestr
char *strrchr(const char *s1, const char *s2);`
char* strcasestr(const char *s1, const char *s2);
sizeof(char)=1
sizeof(int)=4