指针定义
一个指向指针的的指针,它指向的指针是指向一个整型数
int **a;
一个有10个指针的数组,该指针是指向一个整型数的
int *a[10];
一个指向有10个整型数数组的指针
int (*a)[10]
一个指向函数的指针,该函数有一个整型参数并返回一个整型数
int *a( int ){}
一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数
int (* a[10])( int ) //类似这种定义应该采用分解法来做。 先定义单个函数指针 int (*a)(int),然后再是有10个指针的数组 int (*a[10])(int)
关键字static的作用是什么?
1)在函数体内,一个被声明为静态的变量在这一函数被调用过程中维持其值不变(该变量存放在静态变量区)。
2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用
关键字const
const int a; 常量a
int const a; 常量a
const int *a; 指针指向的内容不可以被修改 但是指针指向的地址可以修改。
int * const a; 指针指向的地方不可以被改,但是指向的地址的内容可以修改。
int const * const a; 指针指向地址的内容和指针指向的地址都不可以修改。
第一个设置a的bit 3,第二个清除a 的bit 3
a |= 1 << 3
a &= 0 << 3
或BIC a,a,#0x3
有符号数与无符号数
8.下面的代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6)?puts("> 6") : puts("<= 6");
}
大于6. 有符号数转换为无符号数。
无符号数:不存在正负之分,所有位都用来表示数的本身。
有符号数:最高位用来表示数的正负,最高位为1则表示负数,最高位为0则表示正数。
1. 无符号数转换为有符号数:看无符号数的最高位是否为1,如果不为1(即为0),则有符号数就直接等于无符号数;
2.如果无符号数的最高位为1,则将无符号数取补码,得到的数就是有符号数。
3..有符号数转换为无符号数 :看有符号数的最高位是否为1,如果不为1(即为0),则无符号数就直接等于有符号数;
4.如果有符号数的最高位为1,则将有符号数取补码,得到的数就是无符号数
所以6 - 20 = -14,因为结果作为一个无符号数已经溢出了,所以又加了65536结果变成一个正数了,为65522
-5对应正数5(00000101)→所有位取反(11111010)→加1(11111011)
\0问题
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
//溢出 还有\0void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1[i] = 'a';
}
strcpy( string, str1 );
}
str1没有\0结束符,程序崩溃。void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}改为strlen( str1 ) < 10 这种方式不会报错,但是会造成隐藏的严重bug, 会修改内存里面的数据。
请计算sizeof的值和strlen的值。
void func ( char *str )
{
sizeof( str ) = ?
}
char str[10] = “hello”;
strlen(str);
10和5
宏定义问题
#include "stdafx.h"
#define SQR(X) X*X
int main(int argc, char* argv[])
{
int a = 10;
int k = 2;
int m = 1;
a /= SQR(k+m)/SQR(k+m);
printf("%d\n",a);
return 0;
}
a =a/ (k+m*k+m/k+m*k+m)
用C写个程序,如何判断一个操作系统是16 位还是32 位的?不能用sizeof()函数。
int a = ~0;//把位数全部设为1
if( a>65536 )
{
cout<<"32 bit"<<endl;
}
else
{
cout<<"16 bit"<<endl;
}
在不用第三方参数的情况下,交换两个参数的值.
a=a+b;
b=a-b;
a=a-b;
或者
a = a^b;
b = a^b;
a= a^b;
指针操作
unsigned short array[]={1,2,3,4,5,6,7};
int i = 3;
*(array + i) = ?
结果是4。main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);// (&a+1)指向下一个一维数组
printf("%d,%d",*(a+1),*(ptr-1));
}
解:
int *ptr=(int *)(&a+1);&a表示取得数组a存储区域的首地址,再加1表示数组a存储区域的后的地址,这就使得ptr指针指向数组的最后一个元素后面的那个存储单元的地址,
而ptr减1后,再进行数据访问,则访问的是ptr指针的前一个存储单元的值,所有最后的答案是2,5
(int *)(&a+1) 强制转化指针类型。
#include <filename.h>和 #include “filename.h” 有什么区别?
<>会直接去系统遍历
""会首先在当前项目遍历头文件,如果不存在才去系统遍历。
<>的可以改成"",但是""一定不能改成<>
不能做switch()的参数类型是:
只有整数可以做参数
局部变量能否和全局变量重名。
可以重名。 局部变量名会覆盖全局变量名。 C++中可以使用作用域来区分。
全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
不可以!但是可以声明。 这里涉及到强符号和弱符号的问题,具体的可以参考下面的blog。
在C语言中,函数和初始化的全局变量(包括初始化为0)是强符号,未初始化的全局变量是弱符号。
对于它们,下列三条规则使用:
① 同名的强符号只能有一个,否则编译器报"重复定义"错误。
② 允许一个强符号和多个弱符号,但定义会选择强符号的。
③ 当有多个弱符号相同时,链接器选择占用内存空间最大的那个。
一语句实现x是否为2的若干次幂的判断。
if ( x & ( x - 1 ) == 0 )
printf("是2的幂");
else printf("不是2的幂");
pow(x,y),计算x的y次幂
sqrt(x),求浮点数x的平方根
fabs(x),求浮点数x的绝对值
char* s="AAA";
printf("%s",s);
s[0]='B';
printf("%s",s);
有什么错?
常量区 不允许修改内容,结果不变。AAA
#define MAX 256
int main()
{
unsigned char A[MAX],i;
for (i=0;i<MAX;i++)
A[i]=i;
}
char是一字节,八位,最大可以表示的整数是255,所以这里死循环了
35.struct name1
{
char str;
short x;
int num;
}
struct name2
{
char str;
int num;
short x;
}
typedef struct
{
int a;
char b[3];
short d;
int c;
} node;
sizeof(struct name1)=8
sizeof(struct name2)=12
sizeof(node) = 16
字节对齐
int main()
{
char a;
char *str=&a;
strcpy(str,"hello");
printf(str);
return 0;
}
没有为a分配内存,并且a是一个字符变量。 内存越界。
地址和变量大小操作
unsigned char *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;
请问p1+5= 0x801005; p2+5= 0x810014;
输出结果p1+5的值是801005,因为指针变量指向的值字符,加一表示指针向后移动一个字节,那么加5代表向后移动5个字节,所以输入801005
p5+5的值是801016,因为指针变量指向的长整形的,加一表示指针向后移动4个字节,那么加5代表向后移动20个字节,所以输入810014,(输出时十六进制)要是十进制就是810020了
有数组定义int a[2][2]={ {1},{2,3}};则a[0][1]的值为0。 // 对
int (*ptr) (),则ptr 是一维数组的名字。 // 函数指针
指针在任何情况下都可进行>, <,>=, <=,==运算。 //不明所以
switch(c) 语句中c 可以是int ,long,char ,float ,unsigned int 类型。 //错。 只能是整数,float排除。
不使用库函数,编写函数int strcmp(char *source, char *dest) 相等返回0,不等返回-1;
写一函数int fun(char *p)判断一字符串是否为回文,是返回1,不是返回0,出错返回-1
静态变量操作
#include<stdio.h>
int sum(int a)
{
int c=0;
static int b = 3;//静态
c+=1;
b+=2;
return(a+b+c);
}
int main()
{
int I;
int a=2;
for(I=0;I <5;I++)
{
printf("%d,", sum(a));
}
return 0;
}
8,10,12,14,16,
一定能打印出”hello”的是134,有错误的是2
char *GetHellostr(void);
int main(void)
{
char *ps;
ps= GetHellostr( );
if(ps != NULL)
{
printf(ps);
}
return 0;
}
(1)
char *GetHellostr(void)
{
char *ps=“hello”;
return ps;
}
(2)
char *GetHellostr(void)
{
char a[]=“hello”;
return (char *)a; 内存已经被释放了
}
(3)
char *GetHellostr(void)
{
static char a[]=“hello”;
return (char *)a;
}
(4)
char *GetHellostr(void)
{
char *ps;
ps = malloc(10);
if(NULL ==ps) return NULL;
strcpy(ps,”hello”);
return ps;
}
字符串函数
char* strcpy(char* strDest,const char* strSrc)
{
assert(strDest!=NULL && strSrc!=NULL);
char* strTmp = strDest;
while(*strSrc!='\0')
{
*strDest++ = *strSrc++;
}
strDest = '\0';
return strTmp;
}int strlen(const char*strSrc)
{
assert(strSrc!= NULL);
int len = 0;
while((*strSrc++) != '\0')
++len;
return len;
}char* strcat(char* strDest,const char* strSrc)
{
assert((strDest != NULL) && (strSrc != NULL));
char* strTmp = strDest;
while(*strDest != '\0')
++strDest;
while(*strDest++ = *strSrc++);
*strDest++ = '\0';
return strDest;
}
双指针和指针的引用
void foo(char **p)//双指针
{
*p = "after";
}
int main()
{
int *p = "befor";
foo(&p);
cout << p << endl;//输出的为after
return 0;
}void foo(char *&p)//指针的引用
{
p = "after";
}
int main()
{
int *p = "befor";
foo(p);
cout << p << endl;//输出的为after
return 0;
}
使用汇编语言的原因:
第一:汇编语言执行速率要高于c语言。
第二:启动代码,编写bootloader和内核使用时,主要对cpu和内存进行初始化时使用。因为这个时候还能没有c语言编写的环境(堆栈还没建立),所以不能用c语言。
#ifndef X
#define X
...
#endif
防止头文件被重复包含和编译。
指针与数组的区别。
第1个存储方式的不同数组是存储的成员内容的本身。而指针存储的是首地址。
第2个是运算方式的不同。数组名是一个常量不能进行自增自减的运算,而指针是一个变量,可以进行自增自减的运算。
第3个是赋值运算的操作。数组可以进行初始化操作,但不能通过赋值语句进行整体的赋值,而指针能指向另一条语句。
strcpy 为什么要返回char*
strcpy函数返回的值可以作另一个函数的实参,实现链式操作。
IIC介绍:
开始信号: SCL 为高电平时, SDA 由高电平向低电平跳变,开始传送数据。
结束信号: SCL 为高电平时, SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,
表示已收到数据。 CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号, CPU 接
收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为
受控单元出现故障。//IIC 发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
delay_us(2); //对 TEA5767 这三个延时都是必须的
IIC_SCL=1;delay_us(2);
IIC_SCL=0; delay_us(2);
}
}
//读 1 个字节, ack=1 时,发送 ACK, ack=0,发送 nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA 设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0; delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack) IIC_NAck();//发送 nACK
else IIC_Ack(); //发送 ACK
return receive;
}