C和指针学习

转载 2012年03月29日 01:55:50

http://blog.csdn.net/21aspnet/article/details/2583048

C和指针学习

原则:此文尽量短小精悍,实用,需要扩充阅读都是以链接形式出现

1.编译

#cc program.c

生成a.out文件

 

这个名字是编译器默认的输出名。如果要修改可执行文件的名字可以加-o参数:gcc -o myexec main.c

这样就把main.c编译连接生成的可执行文件命名为myexec

gcc编译器的编译自定义格式

#cc -o hello hello.c

#gcc -o hello hello.c

使用gcc 编译器就会为我们生成一个hello的可执行文件

 扩充阅读:Linux编译器GCC的使用

http://blog.csdn.net/21aspnet/article/details/1534108

http://blog.csdn.net/21aspnet/article/details/167420

补充说明:如果你实在基础很差,那么需要在windows下借助VS2010这样的可视化工具来调试了,这样可以很清晰的看出内存中的指针

http://blog.csdn.net/21aspnet/article/details/6723758

 

2.执行

#./a.out

编译多个源文件

#cc a.c   b.c   c.c

 

3.产生目标文件

#cc -c program.c

产生program.o的目标文件以后供链接用

产生多个目标文件

#cc -c program.c  a.c  b.c

 

编译指定名称文件 

#cc -o sea a.c

4.链接几个目标文件

#cc a.o  b.o  c.o

 

5.转义字符

\\代表\

\\\\代表\\

注意不是\\\代表\\

\'代表'

\"代表"

\n换行

\r回车

 扩充阅读:C语言 格式控制符 和 转义字符

http://blog.csdn.net/21aspnet/article/details/1535459

6.注释

方法一 /*   */

方法二 //

 

7.保留字

 http://blog.csdn.net/21aspnet/article/details/1539252

 

8.整型

singed 有符号

unsigned是无符号的意思,也就是说如果你的编译系统给int分配的存储单元的长度是2个字节的话,有符号的int 取值范围是-32768(即2^15)——32767(即2^15-1),而无符号的unsigned int就是0-65535(2^16-1)

 

类型

最小范围

char

0-127

signed char

-127-127

unsinged char

0-255

int

-32767-32767

long int

-2147483647-2147483647

unsinged int

0-65536

 int a=8;

int a=012;//8进制是0开头

int a=0x0a;//16进制是0x开头

3种输出printf("%d",a);都是10

 

i++和++i
作用一样,就是将i的值加1. 但是如果除了++之外还有别的运算符的话就要考虑先加后加的问题了。 例如: y=i++; 先将i的值赋值给y,再将i的值加1. y=++i; 先将i的值加1,再将i的值赋值给y。

 

 

9.枚举类型

enum A{a,b,c,d};

 

10.浮点

float double long double

 

11.指针

指针只能指向地址!

指针的指针是为了取得“地址”,因为指针只是指向“主体”

int  a;

int *b=&a;

int **c=&b;

a=1;

*b=2;

指针要对应级别,一级b对应一级&a,二级c对应二级&b。

如果传值原代码块无星

main()

{

swap(a,b,c)

}

swap(int a,int *b,int **c)

{

a=*b+**c;//这样不能改变值

*b=a+**c;//可以改变值

}

函数里要改变原值只有指针

printf("%d",*b);//输出2

printf("%d",a);//输出2

 

//指针和字符串

char * ch="abc";

char * cp=ch;

printf("%s",cp);//输出abc

 

//指针和字符

char  ch=‘a’;

char * cp=&ch;

printf("%c",*cp);//输出a

 

//指针和数组

int a1[]={1,2,3,4,5};
printf("%d",&a1[2]);
int *b=&a1[2];

 

扩展阅读:

把指针说透 

http://blog.csdn.net/21aspnet/article/details/317866

C指针本质

 http://blog.csdn.net/21aspnet/article/details/1539652

还看不懂的建议去看:《彻底搞定C指针》

 http://download.csdn.net/source/3491131

 

12.typedef

typedef int k;

k k1=10;

此声明定义了一个 int 的同义字,名字为k。注意 typedef 并不创建新的类型。它仅仅为现有类型添加一个同义字。你可以在任何需要 int 的上下文中使用k

int a=0;

typedef int * p;

p b=&a;

不可以p *b 因为p=int *

 

 

13.const常量

const int a=15;//必须声明时赋值

 int const a=15;//必须声明时赋值,const在前在后都可以

声明好以后再赋值会报错

const int a;

a=15

 

其次:在函数中声明为const的形参在函数被调用时会得到实参的值

int ax(const int aa)

{

int a=aa;

return a+1;

}

扩充阅读:http://blog.csdn.net/21aspnet/article/details/160197

 

14.define常量

#defined MMX 50

printf("%d",MMX);

 

15.链接属性

external外部

internal内部

none无

 

16.变量类型

取变量的值可以直接=变量

给变量赋值一定要&


auto 变量

是用堆栈(stack)方式占用储存器空间,因此,当执行此区段是,系统会立即为这个变量分配存储器空间,而程序执行完后,这个堆栈立即被系统收回.在大括号{}内声明.

static 变量

是C程序编译器以固定地址存放的变量,只要程序不结束,内存不被释放.

static int a=5;

扩充阅读:static

http://blog.csdn.net/21aspnet/article/details/1535573

external 变量
外部变量 定义在程序外部,所有的函数和程序段都可以使用.
头文件f1.h

int a=5;//定义

主文件f2.c

#include "f.h" //引用,注意不能<"f.h">

extern int a;//声明

printf("%d",a);


static external 变量
静态外部变量和外部变量差别在于,外部变量生命可以同时给多个文件使用,而静态外部变量则只能给声明此变量的文件使用.

register 变量

寄存器变量,是由寄存器分配空间,访问速度比访问内存快,加快执行速度.寄存器大小有限.
注意:register int a=1;只能函数内 而不能函数外,由于寄存器的数量有限(不同的cpu寄存器数目不一),不能定义任意多个寄存器变量

extern 和static可以函数外

扩充阅读:寄存器register介绍

http://blog.csdn.net/21aspnet/article/details/257511

扩充阅读:变量属性

 http://blog.csdn.net/21aspnet/article/details/2560072

 

17.语句

if...else...

while循环

i=0;a=0;

while(i<10)

{

a=a+i;

i++;

}

 

break:退出大循环

continue:退出本次循环

fo循环

for(int i=0;i<2;i++)

{

}

do....while

switch

switch(ch){

case "A":

i+1;

break;

case "B":

i+2;

break;

default:

i=0;

}

goto跳转

goto AA;

AA:if...else

 

18.操作符

+-*/%

 

19.位移和位操作符

<<左移

>>右移

&位与

|位或

^位非

扩展阅读:http://blog.csdn.net/21aspnet/article/details/160037

 

20.逻辑运算符

&& ||

 

21.条件运算符

a>5?b-6:c/2

a大于5就执行b-6否则执行c/2

 

22.++

K++ :k不变

++K :K+1

 

23.布尔值

C语言中没有布尔类型。任何一个整型的变量都可以充当布尔变量,用0表示False,其它数(默认为1)表示True。

a = 1;
if(a) {printf("a is T\n");}else{printf("a is F\n");}//输出T
a = 2;
if(a) {printf("a is T\n");}else{printf("a is F\n");}//输出T
a = -1;
if(a) {printf("a is T\n");}else{printf("a is F\n");}//输出T
a = 0;
if(a) {printf("a is T\n");}else{printf("a is F\n");}//输出F
if(!a) {printf("a is T\n");}else{printf("a is F\n");}//输出T

如果你想像Pascal一样使用true和false,那么你可以包含头文件stdbool.h。这样你可以定义变量为bool类型并赋值为true或false。例如:

#include "stdbool.h"
bool a = true;
if (a) printf("a is true");

也可以使用

#define False 0

#define True 1

 

24.数组

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

a[0]//用序号输出数组元素,默认下标从0开始

求数组长度:printf("%d\n",sizeof(a)/sizeof(a[0]));

int *ap=a+2;

ap[0];//输出3

int a[]={1,2,3,4,5,6};//自动计算数组长度

循环数组可以用2种方法

int i;

for(int i;i<6;i++)

{

a[i];这样输出

或者*(a+i);因为*(a)指向数组第一个元素的指针

指针访问数组

int *p=a;注意不是&a;

可以三种方法输出

p[i];方法一就是数组元素

*(p+i);方法二

for()

{

printf("%d",*p);//方法三

p++;

如果  int  const p=a;

用上述代码linux下一样可以编译

 

指针的本质

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

int b[]={6,7,8,9,10} ;

int *p;p=b;

int i;

for(i=o;i<10;i++)

{

prinft("d%",*p);

p++;

}

输出678910 12345

如果改为p=a;

输出12345后面其实是其他未知地址

但是如果改为

p=a;

for(i=-5;i<5;i++)

{

prinft("d%",*p);

p++;

}

输出678910 12345

由此可以看到指针不是孤立的!

 

多维数组

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

a[0][0]=1;

a[0][1]=2;

a[0][2]=3;

int a[2][3]={

{1,2,3},

{4,5,6}

};

多维数组只有第一维可以缺省,其余维都要显示写出

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

//声明指针数组,每个指针元素都初始化为指向各个不同的字符串常量

char const keyword[]={

"do";

"doo";

"doooo";

"do";

"doo";

"do";

"doooooo";

}

//声明矩阵,每一维长度都是9,不够用0补齐

char const keyword[][9]={

"do";

"doo";

"doooo";

"do";

"doo";

"do";

"doooooo";

}

 

扩展阅读:C语言中字符数组和字符串指针分析

http://blog.csdn.net/21aspnet/article/details/1539928

 

25.字符串

类型一:字符串

char day[15] = "abcdefghijklmn";//定义一

char day[] = "abcdefghijklmn";//定义一
char * str="abcdefghijklmn";//定义二

windows下VS2010调试窗口看区别


char str[20]="0123456789";//str是编译期大小已经固定的数组
int a=strlen(str); //a=10;//strlen()在运行起确定
int b=sizeof(str); //而b=20;//sizeof()在编译期确定

sizeof 运算符是用来求内存容量字节的大小的。而strlen是用来求字符串实际长度的。

下面2种声明完全一样

类型二:字符数组

char msg[]={'a','b','c'}

char msg[]={abc}

char *ans;

ans=strchr(day,'c');

printf("%s",ans);//输出从c开始的部分

printf("%d",*ans);//输出找到的指针

ans=strrchr(day,'c');

printf("%s",ans);//输出找到的指针

printf("%d",*ans);//输出找到的指针

 

char temp[100]="hello";

char *t="world";

strcat(temp,t);

输出 temp

要注意的是 第一个参数数组长度要=自身原长+合并字符长

 

类型三:字符串数组

char *a[4]={"this","is","a","test"};
char **p=a;

扩展阅读:C语言字符串处理库函数

 http://blog.csdn.net/21aspnet/article/details/1539970

 

26.结构

注意结构一定要};结束

声明一

struct  simple{

int a;

int b;

};

使用

struct  simple s1;

s1.a=1;

 

声明二

typedef struct {

int a;

int b;

};simple

使用

simple s1;

s1.a=1;

注意:方法二比一少写一个struct

 

结构初始化

typedef struct {

int a;

int b;

};simple{1,2}

使用

simple.a;//输出1

 

指向结构的指针

 

 struct data {

int a;

int b;

};data1{1,2}

struct data *p;

p=&data1;

(*p).a;//输出1

p->b;//输出2

扩展阅读:

结构的成员访问 http://blog.csdn.net/21aspnet/article/details/150259

typedef struct 用法详解和用法小结

typedef的四个用途和两大陷阱

 

27.内联函数

首先要声明

inline int 函数名(参数)

后面要有一个真实的函数体

inline int 函数名(参数)

{

}

只有三二行的代码,建议使用内联!这样运行速度会很快,因为加入了inline 可以减少了,跳入函数和跳出函数的步骤! 

 

28.宏

#define SQUARE(x)   x*x

程序中写SQUARE(3)   实际等于3*3

 

29.函数

int a=1;

int b=2;

ext1(a,b);

ext1(int x.int y)

{

int temp=x;

x=y;

y=temp;

prinft("x=%d,y=%d",x,y)

}

 

30.动态内存分配

动态内存分配是为了链表,否则只能用数组

使用malloc和free分配和释放

#include <malloc.h>//malloc
#include <stdlib.h>//exit’
int * p;

p=malloc(100);

if(p==NULL)

{

printf("Out of memory!\n");

exit(1);

}

实际中p=malloc(sizeof(int));获得足够1个整数的内存
实际中p=malloc(10*sizeof(int));获得足够10个整数的内存

扩展阅读:C语言内存动态分配

http://blog.csdn.net/21aspnet/article/details/146968

 

31.链表

//先定义一个结构体

 typedef struct node{

int data;//数据域

struct node * next;//指针域  ,是struct node的成员,又指向struct node类型的的数据,这里存放下个结点的地址

}Node;

 

建立链表

//返回类型是之前定义的结构体

Node * creat()

//需要先定义3个节点

Node * head=NULL;//头结点

Node *p=NULL;//指向原链表的最后一个结点

Node *s=NULL;//指向新节点

head=(Node*)malloc(sizeof(Node));//动态分配内存空间

head->next=NULL;//开始头结点也就是尾结点

p=head;//p一开始指向头结点

//用while循环

int c=1;//为0是退出循环的条件

int d=0;

while(c)

{

//使用scanf接受用户数据数据

scanf("%d",&d);

if (d!=0)//继续输入

{

s==(Node*)malloc(sizeof(Node));//定义新节点s,和定义head一样

s->data=d;//给新节点赋值

p->next=s;//将第一个结点链接在第二个结点后面

p=s;//p继续指向当前节点

}

else

{

c=0;//用户输入0结束 输入

}

}

p->next=NULL;//结束输入时将最后结点定义为尾结点

return head;

}

//输出结点

output(Node * head)

{

//新定义一个指针用于遍历

//其实如果head->data会是0;单链表巧妙的从第二个结点开始,头结点没用,但是并不代表没用值!

Node * p=head->next;

while(p!=NULL)

{

printf("%d",p->data);

p=p->next;//注意while循环里一定要让P指针不断往下指向

}

}

//查找制定元素的顺序

searchdata(Node *  head)

{

int t=0;

printf("请输入您要查找的值:\n");

scanf("%d",&t);

Node * p=head->next;

int k=0;

while(p!=NULL)

{

k++;

if(p->data==t)

{

printf("%d是第%d个元素:\n",t,k);

break;

}

p=p->next;

}

if(p==NULL)

{

printf("没找到");

}

}

//元素之间插入值 

insertdata(Node *  head)

{

Node *s=NULL;//指向新节点

s=(Node*)malloc(sizeof(Node));//动态分配内存空间

int t=0;

int i=0;

printf("请输入您要查找的值:\n");

scanf("%d",&t);

printf("请输入您要插在那个元素后面:\n");

scanf("%d",&i);

 

Node * p=head->next;

while(p!=NULL)

{

if(p->data==i)

{

s->data=t;

s->next=p->next;//注意是先指向新节点,再改旧节点

p-next=s;

printf("插入成功:\n");

break;

}

p=p->next;

}

if(p==NULL)

{

printf("没找到\n");

}

}

扩展阅读:

链表的C语言实现http://blog.csdn.net/21aspnet/article/details/146968

单链表功能大全 http://blog.csdn.net/21aspnet/article/details/159053

 

 32.scanf

int d=0;

注意是scanf("%d",&d)

这里千万要注意如果写为scanf("d%",&d)一样可以编译通过,但是会引起隐含的bug!!!

 注意是&d而不是d,因为是改变变量的地址对应的内容,而不是直接取其值

 

33.union

联合也叫共同体,和结构struct很像

struct可以定义一个包含多个不同变量的类型,每一个变量在内存中占有自己独立的内存空间,可以同时存储不同类型的数据。 
uniion也可以定义一个包含多个不同变量类型,但这些变量只共有同一个内存空间,每次只能使用其中的一种变量存储数据。

问题是这样做有什么意义?

union{ 
            int   a; 
            float   b; 
            char     c; 
            }a; 
             a.b=10.123;  printf("%d",a.a);

虽然没有初始化a,一样可以使用!union相当于pascal中的变体记录。就像c++中的重载这么方便。

 

34.register寄存器

register int a=1;

但是如果int *b=&a;这样会报错,因为不可以取到寄存器变量的地址

但是使用VS2010调试时可以用&a.

 

35.enum枚举

就是为了定义一组同属性的值,默认的最前面的是0,后面的元素依次+1;
但是注意,每个枚举都唯一定义一个类型,里面的元素的值不是唯一的,枚举成员的初始化只能通过同一枚举的成员进行!!

之所以不用整数而用枚举是为了提高程序的可读性

  1. enum color  
  2. {  
  3. red,  
  4. green=2,  
  5. blue=4  
  6. }colorVal;  
  7.   
  8.   
  9. printf("%d\n",red);   


 

 

36.条件编译

形式一

#ifdef

#else

#endif

形式二

#ifndef

#else

#endif

形式三

#if

#else

#endif

非0 为真

 选择功能是否加入,在编译阶段。

作用一:调试开关。

#define DEBUG//定义可调试 不定义则不

#ifnedf DEBUG

 

#ifdef

作用二:便于确定哪些头文件没有编译

#ifnedf FILE_H_

#define FILE_H_

总结:

#define     定义宏
#undef      取消已定义的宏
#if         如果给定条件为真,则编译下面代码
#ifdef      如果宏已经定义,则编译下面代码
#ifndef     如果宏没有定义,则编译下面代码
#elif       如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif      结束一个#if……#else条件编译块
#error      停止编译并显示错误信息

扩展阅读:http://blog.csdn.net/21aspnet/article/details/6737612


37. size_t  

是为了方便系统之间的移植而定义的 

在32位系统上   定义为   unsigned   int 
在64位系统上   定义为   unsigned   long 

更准确地说法是   在   32位系统上是32位无符号整形 
在   64位系统上是64位无符号整形 

size_t一般用来表示一种计数,比如有多少东西被拷贝等

C_中指针学习的两个绝好例子

  • 2013年04月20日 19:58
  • 21KB
  • 下载

C程序设计(谭浩强)--学习笔记 (指针)

指针运算符*和指针变量说明符*的区别 在指针变量说明中,*是类型说明符,注意:对应的**也是类型说明符,最多是类型不匹配。表示其后的变量时指针类型。 表达式中出现的“*”则是一个运算符,用来表示指...
  • xuleilx
  • xuleilx
  • 2012年03月04日 20:44
  • 1388

c和指针,学习c语言

  • 2012年04月10日 10:28
  • 30.08MB
  • 下载

彻底搞定C指针-C语言学习

  • 2009年01月05日 10:11
  • 263KB
  • 下载

c总结6 --- 在字符串键值对中提取Value(指针学习5)

我们在开发的时候,还有可能会在一段含有键值对中的字符串中进行查找键对应得值,比如:姓名=张三 等等。这样我们就需要借助今天的总结进行操作。   我们需要判断要查找的键是否存在,只有存在的情况下,后面...

C学习指针

  • 2007年08月08日 12:09
  • 30KB
  • 下载

Objective-C学习笔记之结构体以及指针

Objective-C学习笔记之结构体及其指针指针不仅可以指向基本数据类型,还可以指向结构体。 下面贴出代码 struct { int day; ...
  • g535879
  • g535879
  • 2015年07月21日 23:41
  • 212

c和指针-很好的学习教程

  • 2012年07月19日 11:40
  • 28.5MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C和指针学习
举报原因:
原因补充:

(最多只允许输入30个字)