Chinaunix首页 | 论坛 | 博客
  • 博客访问: 683004
  • 博文数量: 516
  • 博客积分: 4119
  • 博客等级: 上校
  • 技术积分: 4288
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-30 17:29
文章分类

全部博文(516)

文章存档

2014年(4)

2013年(160)

2012年(352)

分类:

2012-11-01 12:11:40

原文地址:arm笔记二之c 作者:dingzerong

C programe
long long 8B
{
int i=1;
i *= i-=2;
print i ; =1
}
+a return const
-a return var
no  +++a  /  ++-a  : gcc have bug

gcc -s xx  make to huibian
= nice > , nice

2 num exchange operate way!
a = a + b;
b = a - b;
a = a - b;
当swap(a,b) a=a+b,b=a-b,a=a-b 时 a != b
a++ + a++ + a++ = 3  because x++ more than =

a ^= b ^= a ^= b;
^= have bug!;

EOF = -1;
scanf("%d",yy);  input d into yy ,  yy  is address >|>

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

比较 辨别时
先是把两边的数都转换为相同类型(以更经准的为标准  如:  int i=1;flaot j=1.1f;  则(i==j)  为 false
比较操作会使类型提升,然后在比较

问题:  1 在vim里怎么查找  某函数的源文件???? shift+k
2 printf()函数的变化参数怎么实现的!!!
#include

va_list var;
va_start(var ,value(first argument));
va_arg(var , type(int,flaot,.///));
va_end(var);


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

相同的指针访问 在某些情况下 比下标访问更快!!   如 i++ , 与固定数字相乘 编译时的运算更少一些!

函数 怎么找到的? shift k
   vim  %!xxd 查看2进制文件    -r 变回来
auto
register
static
extern

global const 是真正的常量在rodata段里    而局部const并不是常量在 stark里 (只是编译器不准修改)

const只能const它后面的那个值

这些地址都是虚拟地址  ()                   要通过转换表来调用 实际 物理地址中的数据   ,   这就是内核做的事.
     进程空间 (共3G)  :(从3G-0)  =  
stark ->(高地址到低地址)  |   (auto变量)   局部的const  
heap ->(低地址到高地址)  | (malloc申请的)
bss(未初始化段)   |   (全局变量,static变量  : 未初始化时)
data(低到高)        |         (全局变量,static变量  : 初始化时)  
rodata(只度数据段)     | (常量 " " ) 如: int *p = "xdsfaf"; p就指向rodata,是不能写的   *p = 'x' 会出错!    global const .
test(代码段)   |
                  ...                                       |
bss  data rodata  test  在编译时就确定了
清楚每个变量所处进程空间的位置 !!!!!!!!! (从执行需求的角度来理解. !!!!)  

可执行文件组成????( 查)   ELF 类型可执行文件.什么是什么时候才要的

可执行文件(保存已经初始化的值!!! 要把初始值存在文件里  -- 这就是初始和非初始的区别)   和进程空间.
gcc -Wall 打开所有警告  -g  gdb调试
printf("%p") 打印地址
递归~~

shift+k  在vim里面函数在哪个头文件>?
cvs checkout
cvs update
cvs add


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

offsetof(struct v,var)  可以获取结构体中某一量离其实位置的距离数。
指针就是 4个字节的 无符号数, 就是地址

因为是4个字节所以 能找到的空间为 2^32 = 4G
printf("%p",main)  %p为打印地址

NULL = (void *)0  ???  ,   (void *)可以匹配任何类型指针, 目的就是告诉 这个值是指针。

int p[10] = {};   初始为0. 最好不要这样用!

数组最多分配空间 int[31?,???? 多].char[12??,????]

malloc() 最大小于  0xafff ffff

数组分配空间是 从低到高的  (大端   小端!)

struct xx
{
unsigned  aa  : 2
unsigned  bb  : 3


段位的实现  也通过位操作实现  ,  编译器转换为目标程序时也是通过 位实现的
所以 段位只是为了方便 操作!。
union {
int a;
float b;
} fi = { 3 };  初始化时是 初始第一个!


函数结束时 并不保证内核把 申请的空间回收!!!

(void *)++  是加1

void* malloc(size_t size);
void* calloc(size_t number, size_t elementsize);//空间自动初始为0
void* realoc(void* ptr, size_t new_size);

malloc(num)  总会多分一点 多多少???? google!
向内核申请  空间时  是按页申请的。 并不是按  输入要求。
向高地址扩展的。
realloc(),  能扩展就扩展 不能扩展就重新开辟一段空间。 复制过来原来的。以前的free掉!




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

转换表!
函数指针的数组!

写宏时   有几个语句时   注意    
如:#define hong() xx;xx;xx;  
while()  hong()
这时只在while里执行了一个XX

char *p = "xxxx";
char q[] = "xxxx";
两者是不同的  p指向rodata段  不可修改
q指向stark段  可修改

char *p = (char [])("Xxxx");C99 里才提供的!!!
这时就是在 stark 段.


编译器自定义的宏
有:
__FILE__ 文件名
__LINE__ 当前行
__DATE__ 编译日期
__TIME__ 编译时间
__STDC__ 当前编译器标准

传说中的三种宏技巧:
1 如   #define PRINT(FORMAT,VALUE)  printf("the value is "FORMAT"\n",VALUE)      
    就是可以 用“”“”连接字符串

2 可以用#xx 把xx插入字符串中如
#define PRINT(FORMAT,VALUE)  printf("The value of"#VALUE"is"FORMAT,value)
or  #define PRINT(VALUE)  printf(""#VALUE)

3 可以用##连接符号
#define ADD_FI(value)  sum##value = 4  //  ADD_FI(3) 等价于  sum3=4;

在每个.h文件中加上
#ifndef _XXX_H
#define _XXX_H
...

#ENDIF
防止重复嵌套


I/O函数!!!
同时打开文件个数至少 8个
perror(const char*s)  打印错误格式为   s:xxx(xxx为错误解释)
fflush() 清空

getchar(); putchar();
fgets();fputs();  //读写
fscanf();fprintf();
ungetc();

fread();fwrite();
fseek();ftell();
fgetpos();fsetpos();
rewind();

setbuf();  //改变缓冲方式。
setvbuf();

feof();  //判断文件状态
ferror(); //判断文件错误
clearer(); //清空

tmpfile(); //建立临时文件
tmpnam();  //删除临时文件

对文件的读写操作通常不能直接顺序操作。  
需要用 fseek 来指定操作点。


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

strlen()  计算字符串个数时不把最后的'\n'计算在内
extern xxx ; 只是有说明效果!!!不是定义

考虑边界问题的两个原则:
1 。从最简单的情况下分析,然后将结果外推。
2 。仔细计算边界,决不掉以轻心。

解决边界问题技巧: 采用  半开半闭原则如:
for(i=0;iwhile( --n >=0 )   同上。


因为取数组不能返回数组中所有元素值,所以C就规定 返回这个数组的首地址。
所以    int p[];
&p  p 值相等,类型不同
*(p)就等于 此数组的第一个元素。
*(&p)等于数组

检查有符号溢出可以采用下面方法:
INT_MAX 是一个已定义的常量,代表最大整数值。
检测相加溢出!  
if( a > INT_MAX - b)  溢出!;

可变输入参数的使用!!!
#include
void fun(void first, ...)
va_list var
va_start(var,first)
va_arg(var,type)
va_end(var)



gcc -o xx xx.c -g 生成调试信息 然后可以
gdb xx
r 来调试。


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

使用宏时 要避免 参数中有 副作用的 表达式。
使宏类表达式  而非语句  更安全。
如  
#define assert(e) \
((void)((e) || _assert_error(__FILE__,__LINE__)))
参数最多出现一次


定义内型时  最好用  typedef 而不是宏
因为
#define struct tata*  T1
typedef struct tata* T2
T1 a,b;   此时b就不是指针了。
T2 a,b;

>> he << 移位操作符   最多移动不能超过  移位数据的位数且不能为负如
int a,   int is 32bit    
则可以   a >> 0 , a >> 31 ,   a >> 32 和  a >> -1是不合法的

比较  >  ==  < 操作时会出现类型提升    !!!!!!

== 优先高于  赋值 = 和 位操作

位操作小于加减;;

switch()
{
case x:
derr:
}
中的标号!!可以任意制定.



作业!。

最大重复字串 。

+ - * % ()  运算。

9 + 3 * 33 / 33 -3

147129807



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

c中操作数的计算次序是根据  编译器来确定的。

函数的参数传递 并不是简单的从右往左  压入堆栈。!!

如果想传递真个数组内容  可以通过:
struct aaa{
int xx[xxx];
} ;
将数组放到结构体中,然后传递结构体实现。

函数参数的例子:  常用  signal()  的原型申明!! 来说明。!

void( *signal(int sig,void(*func)(int)))(int);

尽量使用
struct tag{};
而非 typedef struct tag{};  更清晰!

gets()   the data no '\n'
fgets()   the data  have '\n'

cc -o xxx.so -G xx.c
use xx.c make a xxx.so(the share object, dynamic lib)
cc xx.c -L/xxx/xx -R/yyy/yyy
tell cc link and run time how to find the direcatory.

.so is dynamic lib
.a is static lib
cc -lname  =  cc -llibname.so

command   nm   can find something about function

must put the most right    cc  xxx  -lxx

command : ld  about link report

a.out  =  assembler output  

ox0407 is myth number.!!!!
ELF  Extersible Linker Format

In  UNIX  segments is a binary block about file.

use command : size  can look the segments of a programme.  
nm ,can too

BSS = Block Started by Symbol.  is  a  fadel command in IBM704 assembler language.  some people call it Better Save Space.
BSS segment cant put space in object file.

!!!!
1 data segments save in the object file.
2  bss segments dont save in the object file just save size of var.
3   test segments most easy to change the size because gooder.
4 size of a.out is affected by bianyi in debug,but size of segment.

p:120 (int

alloca()  can get stack space

setjump(jump_buf j)  record the information now
longjmp(jump_buf j,int i)  bact to (j)(come from j). is different goto
can use i to distinguish different jump.




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

think how to change   the function return address.
malloc  free   use
brk    sbrk   ,  adjust break printor , it printor heat

mmap//\\  munmap//\\

vmstat

objdump -D    show segments
objdump -d    show test segments

bus error  must  duiqi

caculate num of 1 bit
int func(int num)
{
int count = 0;
while(num != 0)
{
count++;
num &= num - 1;
}
return count;
}

a ^= b^= a^= b;  array cant run.
a continue. -> -> -> -> have problem  .



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

segments have 3 means ,

prionter of function must return value  same
example:
i
  int func(int a,int b,int c)
      function rule!!!
int c  |  addr...
int b |
int a  |nt func(int num,int bum)
  int (*p)() = func;



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

printf("%.*s",n,str)  可以打印str的前n个字节。
printf("%2$s")
gcc -E xxx.c > xxx.i  预处理完了结果
gcc -E xxx.c -o xxx.i
strerror(error).#define XXX(...) printf(__VA_ARGS__)
typeof()
getch(), soon get a char.
宏的可变参数。


use printf operate guangbiao


gcc mke to exec.
.c ->(yuchuli) gcc -E  ->  .i  ->(bian yi)gcc -S  ->  .S  ->  (huibian)   gcc -c  ->  .o  ->  exec

gcc -c xxx.i.s  -> exec

make static lib;
gcc -c ..  .o
ar rcs libname.a  *.o

make dynamic lib:
gcc -fPIC  -g -c xxx.c -o xxx.o
gcc -shared -o libname.so *.o

to exec:
gcc -l -Lpath

LD_LIBRARY_PATH
export LD_LIBRARY_PATH

/etc/ld.so.conf.d/xxx.conf  
ldconfig


ldd look need lib.
nm  exec  look info.

strip asf.o


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

1.3  2.1  2.2  2.3
1.4 1.5  1.6  2.5

#pragma pack(1)   以1个字节对齐
__attibute__((packed))    高诉编译器以1个字节对齐

char xx[0];  可以使用这种方式来记录地址信息

strcut stu{
int num;
int ***;
char name[];
};    
可以!  sizeof(struct stu)   =  8;

strcut stu{
int num;
char name[];
int ***;
};
不行  ,   name不能扩增就不行  。。。。。。

前者name可以扩展。。。。。 相当于  struct...接着的空间也可以用name来使用。


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

setbuf(FILE *stream, char *c)
缓冲方式有:  无缓冲/ 行缓冲 /  完全缓冲  !

setvbuf(FILE *,* buf, mode, size);
当size小于某值时 都规定为无缓冲。   128

sync

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

c中 enum 中的值被看作整形。
而c++中 则类似宏。

结构体初始化可以:
struct xxx n{
.xx = xx;
.yy = xdd;
}

查看ELF
objdump -d D S
readelf -h
ar -t xx.a  可查看xxx,a的组成。
ar -x xxx.a 可以解压xxx.a静态库

gcc --verbose 可打印整个编译过程。
-fno-builitin  bu bb不优化

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

fopen(xa!)  xx 可以是设备文件。/dev/xx;

p 为指针/
free(p);
p的内容不变。

q = p;
p = realloc(p,p);
p 的内容会变化.
q 不一定等于 p;

void func()
{ func();}
递归时注意,堆栈空间溢出!!.

{ } n内可以定义变量
c99前只能先定义,在语句中不能定义。

宏的副作用。
使用 static inline 内联函数代替宏

端位~~!
32位
大端:4321;
小端:1234;
16位
大端:21
小端:12

字节对齐。
windows
#pragma pack(1)   以1个字节对齐
linux
__attribute__((packed))    编译器以1个字节对齐

文档规定!!!端位, 字节对齐。
sorce insight
看源码 软件。
cygvion

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

问题
gcc -I -L能不能递归收缩
Makefile 中的变量会不会被覆盖?

Makefile.am 定义子目录宏的时候会不会?


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

10进制小数表示为2进制时会出现无限循环。产生误差。
如float a=0 ,  for(i=0;i<1000;i++) a+=0.1;
printf(f,a); 就会出现误差。!@

解决方法是现转换为整数int行进行计算 然后再转换回来。!


-------------------------------------------------------------------
问题:
inline 和  #define 的区别


xx.h
static void fun();
#inlcude "xx.h"
static void fun()
{
;
}
gcc -Wall 会有警告 Why?

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

p 为指针/
free(p);
p的内容不变。

q = p;
p = realloc(p,p);
p 的内容会变化.
q 不一定等于 p;

void func()
{ func();}
递归时注意,堆栈空间溢出!!.


用于调试
#ifdef DEBUG
#endif

assert(expertion);
//一个宏
//当expertion为假时会出现错误信息提示.    
//当定义宏  NDEBUG时assert会 在编译时自动去掉。
阅读(422) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~