C

30
Aug
0

新手学c十一:内存管理

1.内存分为

代码段:存储程序代码

数据段:静态、全局数据(有初始化和未初始化是分开的)、 常量

堆区(heap):动态内存分配 主要类实例神马的吧 呵呵 不连续存放

栈区(stack):局部变量 函数参数 自动释放

2.动态内存使用必须引用 stdlib.h

void *malloc(unsigned int size); ?分配空间并复制原空间内容

free

[c]

int *p;

p = (int*)malloc(sizeof(int));//等效 p = malloc(sizeof(int))

if (p != NULL) {

*p = 4;

printf("*p = %d \n",*p);

free(p);

p = NULL;

}

else

{

printf("application is error!");

exit(EXIT_FAILURE);

}

//=======================

*p = 4?

[/c]

2.内存释放

a.free释放了内存 但指针仍然指向该位置 变成野指针

b.除了用free释放 还需要把指针初始化 p =NULL;

3.野指针成因:

a.指针未初始化

b.p被free后 没有置为null 让人误以为是个合法指针

c.指针操作超越了变量作用范围

4.realloc函数

a.malloc基础上增加free原空间内容(初始化为0)

b.改变已经分配的内存 用于增大空间的时候

、、======================

终于完成了初级学习了 ? 感觉没有想象中复杂啊

以前为毛认为那么复杂呢 搞不懂了

接下来重新进入oc部分 继续加油喔

30
Aug
0

新手学c十:位操作与预处理器

1.运算符包括:

& 与?? ?|或? ~取反? ?^异或? ?<<左移? ?>>右移 ? 6种

1字节 = 8位 ?第一位是符号位 1代表负数 0为正数

2.负数的位运算需要将原码转换成补码(原码取反再加1):

如:11010010 ?要转换成00101110

3.与运算

10101101

01101001&

----------------

00101001

使用场合:

a.清零特定位置 开关

b.取某数中的特定位

c.跟1算则不变 跟0则清零

4.或运算

10101101

01101001 ?|

--------

11101101

a.跟1算则真 跟0则不变

5.异或运算

10101101

01101001 ?^

--------

11000100

使用场合:

a.与自身异或 则全部位清零

b.与1异或使特定位值取反 ? 与0则原值不改变

c.不引入第三变量 交换两个变量的值?a = a^b; b= b^a;a=a^b;

6.求反运算

10101101 ?~

--------

01010010

7.左移运算 高位抹除

00001111 ?<< 1

--------

00011110

左移一位相当于*2

[c]

int a,b;

a = 4;

printf("a = %d \n",a);

b = a >> 1;

printf("b = %d \n",b);

//===================

a = 4?

b = 2?

[/c]

8.右移运算

0111 >> 1

---------------

0011

1001 >> 1

---------------

1100

相当于除以2 低位抹除

9.位域

一个字节八位 可以分别存多个开关的状态

struct 位域结构名

{

类型说明符 ?位域名:位域长度

};

a.位域长度不能超过该类型的位数

b.无名域名 表示填充 不能操作

struct srK

{

int a:1

int :2 //该2位不能使用

int b:3

int c:2

}

10.预处理

文件包含

#include <system file name>

#include "user file name" 先找工程文件里找

宏定义 分为有参和无参

无参:

#define 宏名 一串符号

a.名称需要大写

b.不需要加分号

有参:

#define??宏名(参数) 一串符号

#define sum(a,c) a + c * a;

int x = sum(4,3);

条件编译

a.

#define R first

#ifdef R ? ?//#ifndef

#else

#endif

b.

#if 常量表达式
程序段1
#else
程序段2
#endif

29
Aug
0

新手学c九:结构和联合

1.格式:

struct stStudent

{

int nStudentID;

char cSex;

};

struct stStudent stu1,stu2;

也可以这样

struct stStudent

{

int nStudentID;

char cSex;

} stu1,stu2;

赋值:

struct stStudent

{

int nStudentID;

char cSex[];

} stu1={120,"boy"};

2.结构体的名字 可以省略

struct

{

int x;int y;

} xy;

3.结构指针

struct Student *pStu = &boy;

4.访问方法

int a = (*pStu).x;

int a = pStu->x;

5.结构大小

a.总大小是每个成员最大的成员字节数的整数倍

b.首地址能够被最宽基本类型成员的大小所整除

c.结构体每个成员相对结构体首地址的偏移量都是成员大小的整数倍

[c]

struct firstStruct

{

int x;

char str[10];

int f;

char name[3];

int y;

} first = {2,"woshini!"};

void *p;

p = &first;

printf("first POINTER = %d \n" ,p);

p = &(first.x);

printf("x POINTER = %d \n" ,p);

p = &(first.str);

printf("str POINTER = %d \n" ,p);

p = &(first.f);

printf("f POINTER = %d \n" ,p);

p = &(first.name);

printf("name POINTER = %d \n" ,p);

p = &(first.y);

printf("y POINTER = %d \n" ,p);

printf("first sizeof = %d \n" ,sizeof(first));

//================================

first POINTER = 1606416584?

x POINTER = 1606416584?

str POINTER = 1606416588?

f POINTER = 1606416600?

name POINTER = 1606416604?

y POINTER = 1606416608?

first sizeof = 28?

[/c]

6.联合数据类型 :大小为所有成员中占字节最多的成员的大小 所有成员占用相同的内存 只能为第一个成员进行初始化

union unionName

{

float f;

int i;

datatype memberName;

}fi = {1.5};

[c]

void *pp;

union unName

{

int x;

char k[10];

float y;

} ab = {10};

pp = &ab;

printf("ab POINTER = %d \n" ,pp);

pp = &(ab.x);

printf("x POINTER = %d \n" ,pp);

pp = &(ab.k);

printf("k POINTER = %d \n" ,pp);

pp = &(ab.y);

printf("y POINTER = %d \n" ,pp);

printf("ab sizeof = %d \n" ,sizeof(ab));

//===========================

ab POINTER = 1606416552?

x POINTER = 1606416552?

k POINTER = 1606416552?

y POINTER = 1606416552?

ab sizeof = 12?

[/c]

29
Aug
0

新手学c八:指针下

1.字符串指针

char *pszName = "abc";

下面为等效表达式:

char *pszName = NULL;

pszName = "abc";

区别:

char str1[100] = "abc";

char *str2 = "abc";

a.赋值时str1必须单个字节的赋值或用字符函数

b.str2则直接使用=赋值

c.str2实际存储的首地址

[c]

char arrStr[100] = {'F','f','5'}; //arrStr[] = {'F','f','5'} 这样定义 则会溢出

int len = strlen(arrStr);

printf("%s\n",arrStr);

printf("arrStr length = %d \n",len);

char *pszStr =? "i love china!";

printf("pszStr = %s \n",pszStr);

pszStr += 7;

printf("pszStr = %s \n",pszStr);

printf("*pszStr = %c \n",*pszStr);

printf("pszStr's pointer = %p \n",pszStr);

char Str[100] = "i love china!";

printf("Str = %s \n",Str);

printf("Str = %s \n",Str + 7);

//====================================

Ff5

arrStr length = 3?

pszStr = i love china!?

pszStr = china!?

*pszStr = c?

pszStr's pointer = 0x100000ebe?

Str = i love china!?

Str = china!?

//===============================

char s[80];

char *sp = "HELLO";

sp = strcpy(s,sp);

s[0] = 'h';

puts(sp);

printf("\n");

char str[] = "abc\0def\0ghi";

char *p = str;? //此句和 p = &str 一样的效果了

//char *p = &str;

printf("p = %s \n",p+5);

str[0] = 'h';

printf("p = %s \n",p);

//===========================

hELLO

 

p = ef?

p = hbc?

[/c]

2.const指针:const在类型前 则可改地址 不能改内容 const在变量名前 则反之

[c]

int num1 = 10;

int num2 = 20;

const int *p = &num1;? //防止地址内的内容改变

printf("p =? %d \n",*p);

p = &num2;

printf("p =? %d \n",*p);

num2 = 30;

printf("p =? %d \n",*p);

num1 = 10;

num2 = 20;

int *const pNum = &num1;//这次地址不能改变了

printf("pNum =? %d \n",*pNum);

//? ? pNum = &num2;? //wrong

//? ? printf("pNum =? %d \n",*pNum);

*pNum= 30;

printf("pNum =? %d \n",*pNum);

//====================

p =? 10?

p =? 20?

p =? 30?

pNum =? 10?

pNum =? 30?

[/c]

3.指针数组

int *a[10] ;每个元素都是一个指针

[c]

void show(char *p[3])

{

for (int i = 0; i < 3; i++) {

printf("%s \n",p[i]);

}

}

 

int main(int argc, const char * argv[])

{

 

// insert code here...

int i;

char c1[] = "how";

char c2[] = "are";

char *c3 = "you";

char *pArr[3];

pArr[0] = c1;

pArr[1] = c2;

pArr[2] = c3;

for (i = 0; i < 3; i++) {

printf("%s",pArr[i]);

}

printf("\n");

char *arr[3] = {"china", "LDCI","beijing"};

show(arr);

return 0;

}

//=========================

howareyou

china?

LDCI?

beijing?

[/c]

4.数组指针 ?类型名称(*指针名)[数组长度]

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

int (*temp)[5] = &a; ?//指向数组的指针

//不能为 int *temp[4]; 则变成了指针数组 [] 比*的优先级高

//数组个数 必须和原数组相同

//temp +1 相当于temp + 1 * sizeof(数组名)

//访问方式:a[0] ?*(a+0) ? (*temp)[0] ?temp[0][0]

5.二维数组

[c]

int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

int *p = &a[0][0];

printf("p5 = %d \n",p[5]);

printf("a[1][1] = %d \n",a[1][1]);

p++; ? //跳过一个元素

printf("p5 = %d \n",p[5]);

int (*pn)[4] = &a; //一维数组指针 含有四个元素

printf("pn[1][1] = %d \n",pn[1][1]);

pn ++; ? //直接跳过一组

printf("pn[1][1] = %d \n",pn[1][1]);

int (*pnn)[3][4] = &a;//二组数组指针

printf("pnn[0][1][1] = %d \n",pnn[0][1][1]);

pnn ++;//跳过整个数组

//===========================

p5 = 6?

a[1][1] = 6?

p5 = 7?

pn[1][1] = 6?

pn[1][1] = 10?

pnn[0][1][1] = 6?

[/c]

终于完成了指针部分 ?最复杂的还是一或二或多维数组指针 不是它本身复杂 而是不知道为什么要这么搞 用处是什么 = =

继续加油???

28
Aug
0

新手学c七:指针上

终于来到以前很恐惧的地方了,希望这次别被夯死了 ?^_^

估计比较难 暂时打算分几个小单元来学习 = =#

1.概念跟其它语言相同

2.指针可以声明为全局,静态局部 和局部

3.XCODE会自动初始化指针 ,其它系统里据说不会 = =#

[c]? ? int a;

a = 10;

int* pa; //XCODE里指针不初始化 会被自动初始化 = =? 其它系统估计不会

printf("pa pointer %d \n", pa);

pa = &a;//指针存的是地址 要得到变量值 还需要转换回去

printf("pa = %d \n", *pa);

printf("pa pointer %d \n", pa);

*pa = 20;

printf("a = %d \n", a);

printf("pa pointer %d \n", pa);

pa = NULL;

//*pa = NULL;//a = 0;pa地址不变 用上面的则a=20 pa地址为0

printf("pa pointer %d \n", pa);

printf("a = %d \n", a);

//=====================

pa pointer 0?

pa = 10?

pa pointer 1606416620?

a = 20?

pa pointer 1606416620?

pa pointer 0?

a = 20?

[/c]

4.错误赋值方式

[c] ? ?int* px;

*px = 100;

printf("px pointer %d \n", px);

printf("px = %d \n", *px);

[/c]

5.void类型指针:万能 使用前必须进行强制转换

[c]

int a = 10;

int* px =? &a;

*px = 100;

printf("px pointer %d \n", px);

printf("px = %d \n", *px);

void* pvoid;

pvoid = px;

int x;

x = *(int*)pvoid + 1;

printf("x = %d \n", x);

//==================

px pointer 1606416620?

px = 100?

x = 101?

[/c]

6.所有的指量变量的大小都是4个字节

7.指针的整数加减法运算 ?(比较大小时 地址小的大于地址大的

[c]

int arr[5] = {7,2,3,4,5};

int* parr = &arr;

int* p1,p2;

p1 = parr;

parr += 1;

p2 = parr;

printf("*parr = %d \n", *parr);

parr --;

printf("*parr = %d \n", *parr);

printf("p1 pointer = %d \n", p1);

printf("p2 pointer = %d \n", p2);

if (p1 > p2) {

printf("p1 > p2 \n");

}

//=================================

*parr = 2?

*parr = 7?

p1 pointer = 1606416592?

p2 pointer = 1606416596?

p1 > p2?

//================================

int a = 28,b;

char s[10],*p;

p = s;

do {

b = a % 16;

if (b < 10) {

*p = b + 48;

}

else

{

*p = b + 55;

}

p++;

a /= 5;

} while (a > 0);

*p = '\0';

puts(s);

//============================

C51

[/c]

8.循环数组

[c]

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

printf("*arr = %d \n ", *arr );

for (int i = 0; i < 5; i++) {

printf("arr[%d] = %d ",i, *(arr + i)); //+1? 相当于+4个字节 ?4个地址位

}

//

//*arr = 1?

// arr[0] = 1 arr[1] = 2 arr[2] = 3 arr[3] = 4 arr[4] = 5?

//

[/c]

9. ?p++ 增加的地址数 为当前类型单个所占的字节数