c语言,杂项

--------------------------------------------------------------------------------
c语言,打印结构成员的偏移位置。
--------------------------------------------------------------------------------
我们知道,用printf 可以打印变量在内存中的地址。
如果用结构成员变量地址,减去结构的地址,即可得到结构变量的偏移地址。
wait ... 假如结构变量位于地址0, 那么减法就不用算了。
如下例:
将0 强制转换为结构指针,打印该成员变量的地址,可将该地址强制转换为长整数。
例如:printf("s_block offset:%ld\n",(long)&((struct ux_superblock *)0)->s_block);

结构.操作,结构->操作. 就是计算偏移,并解引用之意。
--------------------------------------------------------------------------------

linux c 无bool 型变量,可以用整型变量来实现布尔型变量的功能
用enum 定义 true, false
typedef int bool;
enum
{
 false = 0
 true = 1
};
--------------------------------------------------------------------------------
linux 下, nginx打不开设备,自己写得测试程序可以打开。
原因是因为没有权限。需要把设备权限改为777,而不是默认的660
--------------------------------------------------------------------------------

------------------------------------------------------------
自己分配的内存,从何处可以得到内存的大小?
------------------------------------------------------------
无论是microsoft _msize()
还是linux malloc_usable_size(), 其实现都是在指针的前面, 保留着该内存块的分配大小。
通过观察其反汇编代码,就很容易发现.

int main(int argc, char *argv[])
{
    void *p=malloc(20);
    printf("p is %p\n",p);
//  printf("size is %d\n",_msize(p));
    int i = malloc_usable_size(p);
    printf("size is %d\n", i);
    return 0;
}

--------------------------------------------------------------------------------
程序员工作,就是编辑->编译->连接->调试->编辑.... 循环过程
常见编译,连接错误。

1. 当你引用外部函数时, 外部函数要先声明原型。 声明函数原型的好处是,编译器知道了如何传递参数。

有的语言是无需声明直接使用的,但c语言是先声明后使用的。

以下情况,往往是缺少包含头文件所致。
g++ -c -g -gstabs -O0 -pipe ...... ./joysee-modules/ott//src/diskstore_utility.cpp
./joysee-modules/ott//src/diskstore_utility.cpp: In function ‘int DumpOutSysHeader(int, SYSHEADER*)’:
error: ‘ngx_log_stderr’ was not declared in this scope

2. 当你包含一个头文件时,需要考虑是用c decl, 还是 c++ decl, 这依赖于你的库的编译方式。
c++ decl, 它的名称是包含参数类型的。 如果是c 库, 在c++ 文件中调用, 需要声明
extern "C"
{
}

否则,即使编译通过(已经声明了函数原型),也连接不上。因为目标文件中没有该名字。错误提示如下示:
diskstore_utility.cpp:164: undefined reference to `ngx_log_stderr(int, char const*, ...)'


编译报错: was not declareed.
连接报错: undefined referrence.

------------------------------------------------------------
debug, 调试:有人称排wrong,
调试就是设置断点,查看内存,找出错误原因。或者通过分析log, 找到错误原因来解决问题。

------------------------------------------------------------
执行文件,中文输出是乱码。
  源文件的编码类型会影响执行程序的输出。 要保证cat 源文件不是乱码。则printf 就不是乱码了.

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

c语言 宏定义中#,##用法

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

我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.

展开当前宏函数时,如果形参有#或##则不进行宏参数的展开,否则会进行宏替换。

预处理需要完成的工作:

1. 断行连接. \

2. 注释去除. //, /* .. */

3. 转义字符替换。 \

4. 预处理指令: #

    #include

    #define

    #ifdef, #ifndef #if #endif

    #pragma

    #error

    #warning

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

0!=0 为假, 宏当中经常会用到这种逻辑。处理这种事情,

还是用程序(抽取,简化程序) 去分析逻辑更清晰。人脑有时不如电脑。

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

------------------------------------------------------------
c 语言函数框架
------------------------------------------------------------
     0x00006762 <+0>: push   %edi
  => 0x00006763 <+1>: push   %esi
     0x00006764 <+2>: push   %ebx                                   
     0x00006765 <+3>: sub    $0x20,%esp
进入函数后,进行必要的寄存器入栈保护后, esp 减去一定数值, 这个开辟的空间
就是局部变量区,用"esp+偏移" 即可访问局部变量。
甚至纵使没有局部变量,框架也可能开辟一块esp 缓冲空间。 但是,在函数返回时,
esp 一定要保持平衡即可!

----------------------------------------
little-endian. 与 big-endian. 辨析
----------------------------------------
little-endian 小端序, 是小数据在内存低地址
big-endian 大端序,  是大数据在内存低地址

举例: 0x12345678, (32bits)
little-endian 数据排列: 0x78,0x56,0x34,0x12
big-endian 数据排列:    0x12,0x34,0x56,0x78

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值