C语言基础

一、C语言中判断数据类型或者表达式长度符;不是一个函数,字节数的计算在程序编译时进行,而不是在程序执行的过程中才计算出来。


 char str[ ]="abcd";

sizeof(str)=5

strlen(str)=4


char str[20]="0123456789";
int a=strlen(str); //a=10; >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束。
int b=sizeof(str); //而b=20; >>>> sizeof 计算的则是分配的数组 str[20] 所占的内存空间的大小,不受里面存储的内容改变。  

二、

  void foo(void){
unsigned int a=6;
int b=-20;
if(a+b>6)printf(">6\n");
else printf(">6\n");
}


当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此,从这个意义上讲,无符号数的运算优先级要高于有符号数,这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。 

执行a+b时,b要以unsigned int的形式读取内存中的数据,即将-20的补码按照unsigned int的形式理解读取(4,294,967,276)

也即:b = -20;先转化为 -20 + 2^32 = 4,294,967,276(unsinged int);此时与 a = 6相加必然大于 6

但是如果是与立即数操作,那么不改变b的类型

即   int b=-20;

   b+6 是 等于-14的


三、大小端  判别 方法

  (1)int a=0x1234;
char *p=(char*)&a;
if(*p==0x12) printf("大端模式");
else if(*p==0x34) printf("小端模式");


(2)union w{
int a;
char b;
}temp;
temp.a=1;
if(temp.b==1)printf("小端模式");
else if(temp.b==0)printf("大端模式");
}


四、  求第二大数

   #include<stdio.h>
const int MINNUMBER=-32768;
void sec_max_func(int *,int);
void main(){
int arr[]={2,3,1,4};
int num=sizeof(arr)/sizeof(arr[0]);
printf("num=%d\n",num);
sec_max_func(arr,num);
}
void sec_max_func(int arr[],int num){
int i=1;;
int sec_max=MINNUMBER;
int max=arr[0];
for(;i<num;i++){
if(arr[i]>max)
  {
    sec_max=max;
    max=arr[i];
  }
else {
     if(arr[i]>sec_max)
          sec_max=arr[i];
   }
}
printf("sec_max=%d\n",sec_max);

}

五、将字符串下标m开始往后的字符复制到新字符数组中

   #include<stdio.h>
void strcopy(char *src,char *dest,int m){
char *p1,*p2;
p1=src+m;
p2=dest;
while(*p1) *(p2++)=*(p1++);
*p2='\0';
}
void main(){
int m;
char str1[100]="0123456789",str2[100];
//gets(str1);
scanf("%d",&m);
strcopy(str1,str2,m);
printf("%s\n",str2);
}

六、C 语言中

a^b是按位异或的意思

七、C语言单精度双精度

   

如果是(输出printf)的输出项是double或float时,

可以用%f或%e作为格式描述字符,(其中double也可以用%lf或%le)。

double的意思是可以有16位有效数字,

而在固定格式输出的时候,都默认的是6位,

输出语句printf用double的时候f前面加l是没有效果的,

你要输出长度,可以写,%0.8f,这样就是输出8个有效数字了,要输出几位就改0.后面的参数。


注意:如果是(输入scanf)的输入项为double时,则必须用%lf或%le(必须有个l)作为格式描述字符。

          位于输入项为float与上面的一致。

  void main(){
float a=3.14;
double b=3.141592658;
printf("float=%f\n",a);
printf("double=%0.8f\n",b);
}

八、关于常量池不能被修改 是只读的

  main()
{
 char *s="CEAeded";
char *p=s;
*p='A';
 printf("%s\n",s);
}

该程序崩溃 

char* str = "hello"

   str = "pri"

  prinf("%s",str);有什么问题?直接崩溃,char *s = "hello",hello存在了常量存储区,只能读不能修改

九、不用第三个变量即可更改两个变量的值    经典

   int a=3,b=5;

  a=a+b;

 b=a-b;

a=a-b;

十、关于数组地址

  1、一维数组

  main()
{
 int a[]={1,2,3,4};
 int *p=(int *)(a+1);
 printf("*p=%d\n",*p);
p=(int *)(&a+1);
 printf("&a+1=%d\n",*(p-1));
 printf("*(a+1)=%d\n",*(a+1));
}

a表示数组首元素的地址 即a 与&a[0]是一样的意义;

a+1  表示数组第二个元素的地址 即&a[1]

&a和a和&a[0]结果一样,但是意义不同,&a表示的是指向数组的指针 (int *)(&a+1) 则指向了数组a的 a[5](当然只是这么说,是没有a[5]的。形象的说是偏移到了数组a的长度即sizeof(a)*sizeof(int))

2、关于二维数组     http://blog.csdn.net/david_xtd/article/details/7305586

http://blog.csdn.net/yangchang999/article/details/6664069

虽然a[0]、a都是数组首地址,但二者指向的对象不同。

a[0]是一维数组的名字,它指向的是一维数组a[0]的首元素a[0][0],对其进行“*”运算,得到的是一维数组元素a[0][0]的值即*a[0]与a[0][0]是同一个值。

而a是一个二维数组的名字,它指向的是二维数组a的首元素a[0]对a进行“*”运算,得到的是一维数组a[0]的首地址即*a与a[0]是同一个值。它的指针移动单位是“行”,所以a+i指向的是第i个行数组,即指向a[i]。

当用int *p;定义指针p时,p的指向是一个int型数据,而不是一个地址,因此,用a[0]对p赋值是正确的,而用a对p赋值是错误的。这一点请务必注意。

  int *p=a[0];对的

   对于二维数组a,其a[0]数组由a指向,a[1]数组则由a+1指向,a[2]数组由a+2指向,以此类推。因此,*a与a[0]等价、*(a+1)与a[1]等价、*(a+2)与a[2]等价,┅,即对于a[i]数组,由*(a+i)指向。由此,对于数组元素a[i][j],用数组名a的表示形式为:
*(*(a+i)+j)
指向该元素的指针为:
*(a+i)+j

十一、堆和栈的区别

一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其
操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回
收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的
全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另
一块区域。 - 程序结束后由系统释放。
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。

二、例子程序 
这是一个前辈写的,非常详细 
//main.cpp 
int a = 0; 全局初始化区 
char *p1; 全局未初始化区 
main() 

int b; 栈 
char s[] = "abc"; 栈 
char *p2; 栈 
char *p3 = "123456"; 123456\0在常量区,p3在栈上。 
static int c =0; 全局(静态)初始化区 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); 
分配得来得10和20字节的区域就在堆区。 
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"
优化成一个地方。 
}


十二、

26. MySQL中表test选择10条到20条记录的语句是()
select * from test limit 10,10;     //不会MySQL,忘记关键字limit写错了。 
//多谢xiaozdong指正 
limit是mysql的语法
select * from table limit m,n
其中m是指记录开始的index,从0开始,表示第一条记录
n是指从第m+1条开始,取n条。
select * from tablename limit 2,4
即取出第3条至第6条,4条记录

   十三、 关于#和##

##是连接符号,由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法单元。具体的定义在编译原理里有详尽的解释。

#符是把传递过来的参数当成字符串进行替代


假设程序中已经定义了这样一个带参数的宏:
#define PRINT( n ) printf( "token" #n " = %d", token##n )
同时又定义了二个整形变量:
int token9 = 9;
现在在主程序中以下面的方式调用这个宏:
PRINT( 9 );
那么在编译时,上面的这句话被扩展为:
printf( "token" "9" " = %d", token9 );
注意到在这个例子中,PRINT(9);中的这个”9”被原封不动的当成了一个字符串,与”token”连接在了一起,从而成为了token9。而#n也被”9”所替代。

可想而知,上面程序运行的结果就是在屏幕上打印出token9=9


还有点不明白?

再来一个例子:
#define PRINT( n ) printf( "token" #n " = %d", game##n )
int token9 = 9;
int game9 = 99;
调用:
PRINT(9);
屏幕上打印出:
token9 = 99

十四、*p++ 等价于*(p++)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值