c语言修炼(1)

编程也有一段日子了,觉得要加强一下基础了。估计见解粗俗不堪,仅做个人学习之笔记。

时间复杂度:O(1),常量时间;O(n),线形,随代码长度线形增加;O(n*2),随代码长度的二倍增加;冒泡法的是O(n^2)。

使用extern修饰全局变量

int all=10;
int  sub()
{
 return all;
}

另一个文件中要用all的话:extern all;
void main(){} 

当使用static int all=10的话,extern all;就不行了。这就是static全局变量的作用,限制了作用域。而static局部变量则指初始化一次。static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。

队列先进先出,栈后进先出。

进程和线程的差别。
线程是指进程内的一个执行单元,也是进程内的可调度实体.
与进程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

Heap与stack的差别。
Heap是堆,stack是栈。
Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。
Stack空间有限,Heap是很大的自由存储区
C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。
程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行。

要对绝对地址0x100000赋值,我们可以用
(unsigned int*)0x100000 = 1234;
那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
*((void (*)( ))0x100000 ) ( );
首先要将0x100000强制转换成函数指针,即:
(void (*)())0x100000
然后再调用它:
*((void (*)())0x100000)();
用typedef可以看得更直观些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();


分析下面的程序:
void GetMemory(char **p,int num)
{
*p=(char *)malloc(num);

}
int main()
{
char *str=NULL;

GetMemory(&str,100);

strcpy(str,"hello");

free(str);

if(str!=NULL)
{
strcpy(str,"world");
}

printf("/n str is %s",str);
getchar();
}
输出str is world。
free 只是释放的str指向的内存空间,它本身的值还是存在的.
所以free之后,有一个好的习惯就是将str=NULL.

一语句实现x是否为2的若干次幂的判断
int i = 512;
cout << boolalpha << ((i & (i - 1)) ? false : true) << endl;

& 按位与,| 按位或,^ 按位异或,~ 取反,<< 左移,>> 右移

C 表达式的子表达式以未定顺序求值,允许编译器自由重排表达式的顺序。main() {                     int i;                       i=1;                       //printf("%d,%d,%d/n",i,i++,i++);  
    printf("%d,%d,%d/n",i,++i,++i);
  } 不一定输出什么。

int i;       i=1;                char str[]="abcdef";编译通不过,动态分配的串要写在i=1前面。char str[]=“abcdef”;sizeof(str)值为6。若char* str;printf("%d,",sizeof(str));输出为4。

main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
输出:2,5
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int),指针加1要根据指针类型加上一定的值。

char* s="AAA";
printf("%s",s);
s[0]='B';
printf("%s",s);编译没有错,运行出错。
"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候应当cosnt char* s="AAA";对是s[0]的赋值操作是不合法的。这样就对了:char s[]="AAA";
printf("%s",s);
s[0]=76;
printf("%s",s);

static int i = 100;只初始化一次,再次执行该语句时,以上次调用结束时的值为准。

struct bs
{
int a:8;
int b:2;
int c:6;
}data;
说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。

1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*从下一单元开始存放*/
unsigned c:4
}
在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。

3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:
struct k
{
int a:1
int :2 /*该2位不能使用*/
int b:3
int c:2
};
从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。

unsigned char i,则i的范围是0~255。

struct name1{
char str;
short x;
int num;
}

struct name2{
char str;
int num;
short x;
}

sizeof(struct name1)=8,sizeof(struct name2)=12
在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。

int s[3]={1,2,3};
 char str[]="abcde";
 char* t=str;
 printf("%d,",sizeof(s));//12
 printf("%d,",sizeof(t));//4
 printf("%d,",sizeof(str));//6可见,决定sizeof()值的,只有此变量的声明。

malloc本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。malloc返回值的类型是void *,所以在调用malloc时要显式地进行类型转换,将void * 转换成所需要的指针类型。free不象malloc那样复杂,因为指针p的类型以及它所指的内存的容量事先都是知道的,语句free(p)能正确地释放内存。运算符new使用起来要比函数malloc简单得多,例如:int *p1 = (int *)malloc(sizeof(int) * length);int *p2 = new int[length]; delete []objects;

一个指向函数的指针,该函数有一个整型参数并返回一个整型数 int (*a)(int);

一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数int (*a[10])(int);

在C语言中,关键字static有三个明显的作用:
1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

const int a;
int const a; //前两个一样
const int *a; //指针不可修改,但指向的量可以。
int * const a; //a不可修改

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值