#include 
<stdio.h>

#include
<stdlib.h>


int
main()


{



int
a[5] = { 1, 2, 3, 4, 5 };



int
* ptr1 = (
int
*)(&a + 1);



int
* ptr2 = (
int
*)((
int
)a + 1);


printf(
"%x,%x"
, ptr1[-1], *ptr2);



//ptr1 &a 得到数组首元素地址,+1 ->元素5后面,-1得到5



// a->得到a的地址,转换为int型后,得到4651752,+1->4651753,



//转换为int* 后,得到33554432(我也不知道为什么) 再转为十六进制输出可得


system(
"pause"
);



return
0;

}





#define
_CRT_SECURE_NO_WARNINGS 1



#include
<stdio.h>

#include
<stdlib.h>

int
checkSystem()

{


union
check

{


int
i;


char
ch;

} c;

c.i = 1;


return
(c.ch == 1);

}

int
main()

{


//void* p;


//p++;


//p += 1;


//未知大小 引深为不知道内存目的地址的确切值



//int* pint=NULL;


//pint++; //ANSI:正确


//printf("%d\n", pint);



//void* memcpy(void* dest, const void *src, size_t len);


//void* memset(void* buffer, int c, size_t num);



//int IntArray_a[100];


//memset(IntArray_a, 0, 100 * sizeof(int)); //将 IntArray_a 清 0


//for (int i = 0; i < 100; i++)


//{


// printf("%d ", IntArray_a[i]);


//}



//void 不能代表一个真实的变量,因为在定义变量时,要为变量分配一定的空间,但是


//void型,不能知道它的数据类型大小



/*char * Func(void)

{

char str[30];



return str;

}

*/


//str位于栈内存中,在出了作用域后,便被释放。



//return ;什么也不做,什么也不返回


//const 修饰的是只读变量 具有不可变性


//const 修饰的只读变量必须在定义的同时初始化,因为具有不可变性,如果没有在初始化


//的时候进行初始化,那么在后面点操作中,便不能修改它的值。



/*int i = 0;

const c = 3;

scanf("%d", &i);

switch (i)

{

case 1:

;

break;

case 2:

break;

case c:

break;

}*/


//case 后面只能是常量值,不能是const修饰的只读变量


/*const 定义的只读变量从汇编的角度来看, 只是给出了对应的内存地址, 而不是象#define

一样给出的是立即数,所以,const 定义的只读变量在程序运行过程中只有一份拷贝(因为

它是全局的只读变量,存放在静态区) ,而#define 定义的宏常量在内存中有若干个拷贝。

#define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值。

#define 宏没有类型,而 const 修饰的只读变量具有特定的类型。*/



/*const 修饰一般变量时,放在签名和后面都没有关系

int const i = 2; const int i = 2;*/



//int a = 1;


//int b = 2;


//const int *p=a; // p 可变,p 指向的对象不可变


p = b;


//printf("%d\n", p);



//int const *p; // p 可变,p 指向的对象不可变


//int *const p; // p 不可变,p 指向的对象可变


//const int * const p; //指针 p p 指向的对象都不可变



//struct 的成员默认情况下属性是 public 的,而 class 成员却是 private 的。


/*int ret=checkSystem();

printf("%d\n", ret);*/

system(
"pause"
);


return
0;

}



#include
<stdio.h>

#include
<stdlib.h>

int
main()

{


int
a[5] = { 1, 2, 3, 4, 5 };


int
* ptr1 = (
int
*)(&a + 1);


int
* ptr2 = (
int
*)((
int
)a + 1);

printf(
"%x,%x"
, ptr1[-1], *ptr2);


//ptr1 &a 得到数组首元素地址,+1 ->元素5后面,-1得到5


// a->得到a的地址,转换为int型后,得到4651752,+1->4651753,


//转换为int* 后,得到33554432(我也不知道为什么) 再转为十六进制输出可得

system(
"pause"
);


return
0;

}




#include
<iostream>

using
namespace
std;

int
main()

{


//编译器的确会将注释剔除,但不是简单的剔除,而是用空格代替原来的注释


//C 语言里以反斜杠(\)表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符


//自动接续到前一行。但是注意:反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格。



//左移不管有没有符号位,全部补零


//右移时,符号位随同移动,为正时,补0,负数时 补1

system(
"pause"
);


return
0;

}









一维数组做参数时,将一维数组解析为指向数组首元素地址的指针,


char* (*fun1)(char* p1, char* p2); 函数指针,指向一个函数的指针

例:



#include
<stdio.h>


#include
<stdlib.h>


#include
<string.h>


char
* fun(
char
*
p1
,
char
*
p2
)


{



int
i = 0;


i = strcmp(
p1
,
p2
);



if
(0 == i)


{



return
p1
;


}



else


{



return
p2
;


}


}


int
main()


{



char
* (*pf)(
char
* p1,
char
* p2);


pf = &fun;
//pf = fun; //也是可以的,因为函数名在编译时,其实就是个地址



//创建一个函数指针pf,pf指向fun,(*pf)("aa", "bb")调用函数


(*pf)(
"aa"
,
"bb"
);


system(
"pause"
);



return
0;

}




#include
<stdio.h>


#include
<stdlib.h>


void
Function()


{


printf(
"Call Function!\n"
);


}


int
main()


{



//void(*p)()定义一个指针p 参数列表和返回值全为空,&p求指针变量p的地址,强转为int*



//类型,表示将地址强制转换成指向 int 类型数据的指针,,Function为函数的首地址,



//多以这段代码的意思是,将函数Function的入口地址强制强转为int类型后,在赋值给



//指针变量p



void
(*p)();


*(
int
*)&p = (
int
)Function;


(*p)();


system(
"pause"
);



return
0;

}



(*(void(*)())0)()分析

1.void(*)() 是一个函数指针,函数列表为空,返回值为空,

2.void(*)() 0 ,将0转换为一个函数类型的指针,0是一个地址,将函数存放在首地址为0的地方

3.(*(void(*)())0) ,将首地址0中的内容取出来,

4.(*(void(*)())0)() ,函数调用


静态区: 保存自动全局变量和static变量(包括static全局和static局部),静态区的内容在整个生命周期都存在,内容有编译器在编译的时候分配,只初始化一次,

栈: 保存局部变量,栈上的内容只在函数范围内存在,当出了函数的作用域时,会被自动销毁,特点:效率高,空间大小有限

堆:有malloc/new 分配空间,有free/delete释放,注意配对使用,容易出错。
#include 
<stdio.h>

#include
<stdlib.h>


int
main()


{



int
a[5] = { 1, 2, 3, 4, 5 };



int
* ptr1 = (
int
*)(&a + 1);



int
* ptr2 = (
int
*)((
int
)a + 1);


printf(
"%x,%x"
, ptr1[-1], *ptr2);



//ptr1 &a 得到数组首元素地址,+1 ->元素5后面,-1得到5



// a->得到a的地址,转换为int型后,得到4651752,+1->4651753,



//转换为int* 后,得到33554432(我也不知道为什么) 再转为十六进制输出可得


system(
"pause"
);



return
0;

}





#define
_CRT_SECURE_NO_WARNINGS 1



#include
<stdio.h>

#include
<stdlib.h>

int
checkSystem()

{


union
check

{


int
i;


char
ch;

} c;

c.i = 1;


return
(c.ch == 1);

}

int
main()

{


//void* p;


//p++;


//p += 1;


//未知大小 引深为不知道内存目的地址的确切值



//int* pint=NULL;


//pint++; //ANSI:正确


//printf("%d\n", pint);



//void* memcpy(void* dest, const void *src, size_t len);


//void* memset(void* buffer, int c, size_t num);



//int IntArray_a[100];


//memset(IntArray_a, 0, 100 * sizeof(int)); //将 IntArray_a 清 0


//for (int i = 0; i < 100; i++)


//{


// printf("%d ", IntArray_a[i]);


//}



//void 不能代表一个真实的变量,因为在定义变量时,要为变量分配一定的空间,但是


//void型,不能知道它的数据类型大小



/*char * Func(void)

{

char str[30];



return str;

}

*/


//str位于栈内存中,在出了作用域后,便被释放。



//return ;什么也不做,什么也不返回


//const 修饰的是只读变量 具有不可变性


//const 修饰的只读变量必须在定义的同时初始化,因为具有不可变性,如果没有在初始化


//的时候进行初始化,那么在后面点操作中,便不能修改它的值。



/*int i = 0;

const c = 3;

scanf("%d", &i);

switch (i)

{

case 1:

;

break;

case 2:

break;

case c:

break;

}*/


//case 后面只能是常量值,不能是const修饰的只读变量


/*const 定义的只读变量从汇编的角度来看, 只是给出了对应的内存地址, 而不是象#define

一样给出的是立即数,所以,const 定义的只读变量在程序运行过程中只有一份拷贝(因为

它是全局的只读变量,存放在静态区) ,而#define 定义的宏常量在内存中有若干个拷贝。

#define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值。

#define 宏没有类型,而 const 修饰的只读变量具有特定的类型。*/



/*const 修饰一般变量时,放在签名和后面都没有关系

int const i = 2; const int i = 2;*/



//int a = 1;


//int b = 2;


//const int *p=a; // p 可变,p 指向的对象不可变


p = b;


//printf("%d\n", p);



//int const *p; // p 可变,p 指向的对象不可变


//int *const p; // p 不可变,p 指向的对象可变


//const int * const p; //指针 p p 指向的对象都不可变



//struct 的成员默认情况下属性是 public 的,而 class 成员却是 private 的。


/*int ret=checkSystem();

printf("%d\n", ret);*/

system(
"pause"
);


return
0;

}



#include
<stdio.h>

#include
<stdlib.h>

int
main()

{


int
a[5] = { 1, 2, 3, 4, 5 };


int
* ptr1 = (
int
*)(&a + 1);


int
* ptr2 = (
int
*)((
int
)a + 1);

printf(
"%x,%x"
, ptr1[-1], *ptr2);


//ptr1 &a 得到数组首元素地址,+1 ->元素5后面,-1得到5


// a->得到a的地址,转换为int型后,得到4651752,+1->4651753,


//转换为int* 后,得到33554432(我也不知道为什么) 再转为十六进制输出可得

system(
"pause"
);


return
0;

}




#include
<iostream>

using
namespace
std;

int
main()

{


//编译器的确会将注释剔除,但不是简单的剔除,而是用空格代替原来的注释


//C 语言里以反斜杠(\)表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符


//自动接续到前一行。但是注意:反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格。



//左移不管有没有符号位,全部补零


//右移时,符号位随同移动,为正时,补0,负数时 补1

system(
"pause"
);


return
0;

}









一维数组做参数时,将一维数组解析为指向数组首元素地址的指针,


char* (*fun1)(char* p1, char* p2); 函数指针,指向一个函数的指针

例:



#include
<stdio.h>


#include
<stdlib.h>


#include
<string.h>


char
* fun(
char
*
p1
,
char
*
p2
)


{



int
i = 0;


i = strcmp(
p1
,
p2
);



if
(0 == i)


{



return
p1
;


}



else


{



return
p2
;


}


}


int
main()


{



char
* (*pf)(
char
* p1,
char
* p2);


pf = &fun;
//pf = fun; //也是可以的,因为函数名在编译时,其实就是个地址



//创建一个函数指针pf,pf指向fun,(*pf)("aa", "bb")调用函数


(*pf)(
"aa"
,
"bb"
);


system(
"pause"
);



return
0;

}




#include
<stdio.h>


#include
<stdlib.h>


void
Function()


{


printf(
"Call Function!\n"
);


}


int
main()


{



//void(*p)()定义一个指针p 参数列表和返回值全为空,&p求指针变量p的地址,强转为int*



//类型,表示将地址强制转换成指向 int 类型数据的指针,,Function为函数的首地址,



//多以这段代码的意思是,将函数Function的入口地址强制强转为int类型后,在赋值给



//指针变量p



void
(*p)();


*(
int
*)&p = (
int
)Function;


(*p)();


system(
"pause"
);



return
0;

}



(*(void(*)())0)()分析

1.void(*)() 是一个函数指针,函数列表为空,返回值为空,

2.void(*)() 0 ,将0转换为一个函数类型的指针,0是一个地址,将函数存放在首地址为0的地方

3.(*(void(*)())0) ,将首地址0中的内容取出来,

4.(*(void(*)())0)() ,函数调用


静态区: 保存自动全局变量和static变量(包括static全局和static局部),静态区的内容在整个生命周期都存在,内容有编译器在编译的时候分配,只初始化一次,

栈: 保存局部变量,栈上的内容只在函数范围内存在,当出了函数的作用域时,会被自动销毁,特点:效率高,空间大小有限

堆:有malloc/new 分配空间,有free/delete释放,注意配对使用,容易出错。