内存类型资源地址、门牌号的代名词
指针:地址的代名词
指针变量:存放指针这个概念的盒子
*P
char *p
*p;
C语言娟译器对指针这个特殊的概念,有2个疑问?
1、分配一个盒子,盒子要多大?
在32bit系统中,指针就4个字节
2、盘子里存放的地址所指向内存的读取方法是什么?
3、指针指向内容空间,一定要保证合法性。
#include
int main()
{
int *p1;
char *p2;
printf("the p1 is %u,p2 is %u\n",sizeof(p1),sizeof(p2));
return 0;
}
返回值(64位系统):
```bash
E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
the p1 is 8,p2 is 8
读内存空间(int):
#include
int main()
{
int a = 0x12345678;
int *p1;
p1 = &a;
printf("the p1 is %x\n",*p1);
return 0;
}
// 返回值
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// the p1 is 12345678
读内存空间(char):
#include
int main()
{
int a = 0x12345678;
char *p1;
p1 = &a;
printf("the p1 is %x\n",*p1);
return 0;
}
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:8:8: warning: assignment from incompatible pointer type [enabled by default]
// the p1 is 78
浮点数的存储(形式非常特殊)
显示方法1:
#include
int main()
{
float a = 1.2;
int *p;
p = &a;
printf("the p1 is %x\n",*p);
return 0;
}
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:8:7: warning: assignment from incompatible pointer type [enabled by default]
// the p1 is 3f99999a
显示方法2:
#include
int main()
{
float a = 1.2;
unsigned char *p;
p = &a;
printf("the p1 is %x\n",*p);
return 0;
}
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:9:7: warning: assignment from incompatible pointer type [enabled by default]
// the p1 is 9a
注意:如果用char *p,会打印符号位,导致显示为:the p1 is ffffff9a。
内存用性:
1、内存操作的大小
2、内存的变化性,可写可读
const char *p 【推荐】 字符串常量 p是门牌号
char const *p 同上,
char *const p【推荐】 硬件资源 LCD 指向固定地址,内容可以刷新
char *p const 同上,
const char *const p ROM
示例:
#include
int main()
{
char *p = "hello world!\n";
char buf[] = {"hello world!\n"};
char *p2 = buf;
printf("the one is %x\n",*p);
*p2 = 'a'; //不合法,会出现段错误
printf("%s\n",p2); //无输出
return 0;
}
正确的写法应该是:
const char p = “hello world!\n”;
此时p2 = 'a’编译器提示错误:
E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
2.c: In function 'main':
2.c:11:5: error: assignment of read-only location '*p'
volatile
防止编译器优化指向内存地址,每次都要强制更新或者执行地址所指的值
volatile char *p
*p== 0x10
while(p == 0x10 );
xxx
typedef
char *p;
什么类型,变量名称;
char *name_t; name_t是一个指针(存储地址的盒子),指向了一个char类型的内存
typedef char *name_t; name_t是一个指针类型的名称(别名),指向了一个char类型的内存
name_t abc;
++,–,+,-
int *p = xxx [0x12]
p+1 [012+1(sizeof(*p))] +1是指向下一个单位,操作的是单位。
指针的加法运算,实际上加的是一个单位,单位的大小可以使用sizeof(p[0])
int *p p+1
char *p p+1
p++ p-- 更新地址
[]
变量名[n] p+n等到地址, p[n]自动将该地址的内容取出来
n ID 标签
地址内容的标签访问方式,取出标签里的值。
#include
int main()
{
int a = 0x12345678;
int b = 0x99991199;
int *p1 = &b; //指针与地址类型一致
char *p2 = (char *) &b; //如果不强制转换,编译器会报警告,变量类型与指针不一样
printf("the p1+1 is %x ,or is %x, *p1+1 is %x\n",*(p1+1),p1[1],*p1+1);
printf("the p2+1 is %x \n",p2[1]);
return 0;
}
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// the p1+1 is 64fe14 ,or is 64fe14, *p1+1 is 9999119a
// the p2+1 is 11
与教程有差异,没有得到预想的结果,见图:
另外对于const的缺陷,编译器也做了优化,不再能够修改,如一下代码:
#include
int main()
{
const int a = 0x12345678; //编译器告知结果
int b = 0x11223344;
//a = 100; //2.c:8:5: error: assignment of read-only variable 'a'
int *p = &b;
//*(p+1);
p[1] = 0x100;
printf("the a is %x\n",a);
return 0;
}
// p[1] = 0x100未能实现
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// the a is 12345678
const的详细解释:可参考C语言中的const
P+1与*(P+1)的延伸可参考:关于C语言中二维数组的P+1与*(P+1)个人浅见
逻辑操作符>= <= == !=
1、跟一个特殊值进行比较,0x0,地址的无效值,结束标志。
if (p==0x0);
建议用NULL进行比较。
2、指针必须是同类型的比较才有意义
char *
int *
#include
int main()
{
int a = 0x12345678; //编译器告知结果
int b = 0x99991199;
int *p1 = &b;
char *p2 = (char *)&b;
if(p1 >= p2){
printf("===========\n");
}
// printf("the a is %x\n",a);
return 0;
}
// E:\temp>cd "e:\temp\" && gcc 2.c -o 2 && "e:\temp\"2
// 2.c: In function 'main':
// 2.c:12:11: warning: comparison of distinct pointer types lacks a cast [enabled by default]
int **p;
存放地址的地址空间,
如:char **p 描述内存与内存之间的线性关系,
p[m]==NULL —>二维空间结束了(结束标志)
#include
int main(int argc,char **argv)
{
int i;
for(i = 0;i < argc;i++){
printf("the argv[%d] is %s\n",i,argv[i]);
}
return 0;
}
// gcc 2.c -o 2
// E:\temp>2 123 456
// the argv[0] is 2
// the argv[1] is 123
// the argv[2] is 456
#include
int main(int argc,char **argv)
{
int i = 0;
while(argv[i] != NULL){
printf("the argv is %s\n",argv[i]);
i++;
}
return 0;
}
// E:\temp>2 123 456
// the argv is 2
// the argv is 123
// the argv is 456