预处理:
-----------------------------------------------------------------------------------------------
#include <stdio.h>
#define SQR(x) ((x)*(x)) //注意这种定义方式,加括号
int main()
{
int a = -3;
int b = -2;
int q = a/b;
int r = a%b;
printf("q = %d\n",q); //q = 1
printf("r = %d\n",r); //r = -1
//__DATE__,__TIME__ 表示的是编译时的时间,而不是运行时
printf("line = %d\nfile = %s\ndate = %s\ntime = %s\n",\
__LINE__,__FILE__,__DATE__,__TIME__);
//关于宏定义
printf("SQR(1)\n"); //--SQR(1);注意
#define X 3
#define Y X*3
#undef X
#define X 2
int z = Y;
printf("z = %d\n",z); //--z = 6;
#define _X86
#ifdef _X86
#pragma message("X86 macro activated!")
#endif
/************************************************/
//内存对齐
/************************************************/
struct TestStruct1
{
char c1;
short s;
char c2;
int i;
};
struct TestStruct1 ts1;
printf("c1 %p, s %p, c2 %p, i %p\n", //--c1 (nil), s 0x2, c2 0x4, i 0x8 解释:内存对齐
(unsigned int)(void *)&ts1.c1 - (unsigned int)(void *)&ts1,
(unsigned int)(void *)&ts1.s - (unsigned int)(void *)&ts1,
(unsigned int)(void *)&ts1.c2 - (unsigned int)(void *)&ts1,
(unsigned int)(void *)&ts1.i - (unsigned int)(void *)&ts1);
printf("sizeof(ts1) = %d\n",sizeof(ts1)); //--sizeof(ts1) = 12.注意,这里不是结构体成员之和8
//PS:这里可在前面加上一句#pragma pack(1),使其按一个字节对齐。但是会降低程序效率,访问需要两个机器周期
//也可以通过改变结构体TestStruct1中的成员顺序来优化程序。这样不会降低效率,而且可以消除其他很多问题。
//例如,作为库被第三方软件使用时。
/************************************************/
//其他一些预处理
/************************************************/
#pragma pack(8)
typedef struct
{
char a;
long b;
}TestStruct2;
struct TestStruct3
{
char c;
TestStruct2 d;
long long e;
};
#pragma pack()
struct TestStruct3 ts3;
printf("sizeof(ts3) = %d\n",sizeof(ts3)); //--sizeof(ts3) = 20 || 24
#define SQR(x) printf("The square of "#x" is %d.\n",((x) * (x)));
SQR(8);
#define XNAME(n) x##n //如:XNAME(8)展开后为x8
//PS:#和##应该尽量不用,在一个的宏定义中,最多可以出现一次"#"或"##"
/************************************************/
return 0;
}
符号:
---------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
//注释符
/****************************************/
//在编译时,编译器会将注释符替换为空格
int /*...*/i; //--正确
char * s = "abcdefgh //ijklmn"; //--正确
//Is it a\
valid comment? //--正确
// in/*...*/t j; //--错误
/*****************************************/
//左移和右移
/****************************************/
//对于有符号数,在右移时,符号位将随同移动。当为正数时,
//最高位补0;而为负数时,符号位为1,最高位是补0或是补1
//取决于 编译系统。
0x01 << 2 + 3; //-----结果为32,因为 + 优先级高
//左移和右移的位数不能大于数据的长度,不能小于0.
// 0x01 << 2 + 30; //错误
// 0x01 << 2 - 3; //错误
/***************************************/
//关于++和--
/*************************************/
int a = 3;
int b = (++a) + (++a) + (++a);
printf("a = %d\n",a); //a = 6
printf("b = %d\n",b); //b = 16 (5+5+6)。结果由编译器定,有的编译器结果为18。
int c = 0;
int d = (c++,c++,c++); //d = 2 C语言遇到逗号,认为本计算单位结束,所以最后一个生效
c = 0;
int e = (++c,c++,c+10); //依次为e=1,e=1,e=12;
printf("d = %d\n",d); //d = 2;
printf("e = %d\n",e); //e = 12;
c = 0;
int f = (c++) + (c++) + (c++);
printf("f = %d\n",f); //f = 0;上式c遇到分号才认为本计算
// 单位结束,此时c才做自加动作.
/* 这段程序会陷入一个死循环,主要问题在 g < 10,printf("Second = %d\n",g);
int g;
for (g = 0,printf("First = %d\n",g);\
g < 10,printf("Second = %d\n",g);\
g++,printf("Third = %d\n",g))
{
printf("Fourth = %d\n",g);
}
*/
int h = 1,m = 2;
int k;
k = h+++m;
printf("k = %d\n",k); //k = 3,说明 h+++m = (h++) + m
/***********************************/
return 0;
}
sizeof于strlen:
-------------------------------------------------------------------------------------------------------------
/*
%u无符号十进制整数 %lu无符号长整型
%d有符号十进制整数 %lf double
%0无符号八进制 %g double
%x无符号十六进制整数 %i == %d
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int fun(int b[])
{
return sizeof b;
}
int main()
{
//关于sizeof
char *p = NULL ;
// int num = sizeof i;
printf("sizeof(p) = %d\n",sizeof(p)); //sizeof(p) = 4
printf("sizeof(*p) = %d\n",sizeof(*p)); //sizeof(*p) = 1
int a[100];
printf("sizeof(a) = %d\n",sizeof(a)); //sizeof(a) = 400
printf("sizeof(a[100]) = %d\n",sizeof(a[100])); //sizeof(a[100]) = 4
printf("sizeof(&a) = %d\n",sizeof(&a)); //sizeof(&a) = 4
printf("sizeof(&a[0]) = %d\n",sizeof(&a[0])); //sizeof(&a[0]) = 4
printf("&a = %p\n",&a); //&a = 0xbfdd5aec
printf("&a[0] = %p\n",&a[0]); //&a[0] = 0xbfdd5aec
int b[100];
printf("sizeof(b) = %d\n",fun(b)); //sizeof(b) = 4
/*****************************************/
char tp1[] = {'Q','W','E','R'};
char tp2[] = "qwer";
printf("strlen(tp1) = %d\n", strlen(tp1)); // 7(这是一个不确定的数,遇到'\0'判断为结束)
printf("sizeof(tp1) = %d\n", sizeof(tp1)); // 4
printf("strlen(tp2) = %d\n", strlen(tp2)); // 4
printf("sizeof(tp2) = %d\n", sizeof(tp2)); // 5
/*****************************************/
struct student
{
}stu;
printf("sizeof(stu) = %d\n",sizeof(stu)); //sizeof(stu) = 0
typedef struct st_type //柔性数组
{
double i;
int a[]; // 或[int a[0]
}type_a;
type_a *tp = (type_a *)malloc(sizeof(type_a) + 100 * sizeof(int));
printf("sizeof(type_a) = %d\n",sizeof(type_a));//sizeof(type_a) = 8
printf("sizeof(*tp) = %d\n",sizeof(*tp)); //sizeof(*tp) = 8,柔性数组不占结构体编制,
//不能算结构体的正式成员
free(tp);
printf("\n");
/**********************************************/
但是:
typedef struct
{
char *s[50];
}memo;
问:sizeof(memo) = 200;
/*字符为有符号数,只有七位有效,即取值范围为-256到255*/
/*********************************************/
char c[1000];
int i;
for(i = 0; i < 1000; i++)
{
c[i] = -1 - i;
}
printf("strlen(c) = %d\n",strlen(c)); //strlen(c) = 255
printf("\n");
/*********************************************/
/*sizeof与strlen()*/
/********************************************/
char d[3];
char *e = "abcde";
printf("strlen(d) = %d\n",strlen(d)); //strlen(d) = 0
printf("sizeof(d) = %d\n",sizeof(d)); //sizeof(d) = 3
printf("strlen(e) = %d\n",strlen(e)); //strlen(e) = 5
printf("sizeof(e) = %d\n",sizeof(e)); //sizeof(e) = 4
printf("\n");
/*******************************************/
//下面这段代码会陷入死循环 ,因为k为无符号数,
//永远不可能 < 0,如果把k >= 0改为(int)k >= 0即可。
/*************************************
unsigned k;
for (k = 9; k >= 0; k--)
{
printf("%u\n",k);
}
************************************/
/*const修饰的变量可以用在case后*/
const int k = 2;
switch(k)
{
case 1: printf("Is 1\n");
break;
case 2: printf("Is 2\n");
break;
case 3: printf("Is 3\n");
break;
default:
break;
}
printf("\n");
/**********************************/
/*
const int *p; //p可变,p指向的对象不可变
int const *p; //p可变,p指向的对象不可变
int *const p; //p不可变,p指向的对象可变
const int *const p; //p不可变,p指向的对象不可变
*/
/*
const volatile int x = 10;
x = 2; //错误,上面一条一句,虽然能
编译通过,但是x被const修饰
*/
/*********************************/
int f[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&f + 1);
int *ptr2 = (int *)((int)f + 1);
printf("%p\n",f); //0xbf8b6894
printf("%p\n",ptr1); //0xbf8b68a8
printf("%p\n",ptr2); //0xbf8b6895
printf("%x, %d",ptr1[-1],*ptr2); //5, 33554432
printf("\n");
/******************************/
//枚举
/******************************/
enum Color
{
GREEN = 1,
RED,
BLUE,
GREEN_RED = 10,
GREEN_BLUE
}ColorVal;
printf("sizeof(ColorVal) = %d\n",sizeof(ColorVal));//sizeof(ColorVal) = 4
printf("\n");
/******************************/
/********************************
typedef struct student
{
//code
}Stu_st,*Stu_pst;
//
A)struct student stu1 = Stu_st stu1;
B)struct student *stu2 = Stu_pst stu2 = Stu_st *stu2;
//
//另:const修饰的是变量而不管类型,包括typedef定义的类型
// 而typedef是对类型的重定义,而不是 变量。
********************************/
/*
#define INT32 int
typedef int int32;
int32 abc = 10; //正确
unsigned int32 bcd = 10; //错误,因为此时int32已是新的数据类型
unsigned INT32 cde = 10; //正确,这里只是简单替换
*/
return 0;
}
指针:
-------------------------------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int b = *a;
printf("b = %d\n",b); //--b = 1;这里的a作为右值相当于&a[0]
char *p = "abcdef";
//对指针的访问
printf("&p = %p\n",&p); //--&p = 0xbfe5af48;指针P的地址
printf("p address = %p\n",p); //--p address = 0x8048588;指针P存放的地址
printf("p = %s\n",p); //--p = abcdef;整型数组就不能用这种方式打印
printf("*p = %c\n",*p); //--*p = a
printf("* (p + 4) = %c\n",* (p + 4));//--* (p + 4) = e
printf("p[4] = %c\n",p[4]); //--p[4] = e
//对数组的访问
char ca[] = "123456";
printf("*ca = %c\n",*ca); //--*ca = 1
printf("* (ca + 4) = %c\n",* (ca + 4));//--* (ca + 4) = 5
printf("ca = %s\n",ca); //ca = 123456
//PS:这里的偏移量是指元素的个数,而不是字节数,如果是整型数组,
//一个偏移量就表示4字节。
int c[5] = {1,2,3,4,5};
int *ptr = (int *)(&a + 1);//&a + 1相当于 &a + sizeof(a),因为a是一个数组,其数据类型长度是5 * sizeof(int)
printf("%d, %d\n",*(a + 1), *(ptr - 2));//--2, 4
//PS:c的数据类型是一个包含5个成员的整型数组,其大小是5 * sizeof(int);
//而&c + 1就表示移动一个5*sizeof(int)的大小,即下一个数组的首地址。
//而ptr是一个整型指针,其数据类型长度为sizeof(int),所以ptr -2即为ptr - 2*sizeof(int)
//c + 1是数组下一元素首地址。&c + 1是下一数组首地址。c = &c[0]
char *pc = c; //警告:虽然可以得到结果,但是这里隐含错误,类型不一致。
printf("*(pc + 4) = %d\n",*(pc + 4));//--*(pc + 4) = 2
char x[10] = {'A','B','C','D','E','F','G','H','I','J'};
char (* p3)[3] = &x; //警告:initialization from incompatible pointer type
char (* p4)[3] = x; //警告:这里数据类型不一致
printf("p3 + 2 = %s\n",p3 + 2); //p3 + 2 = GHIJ;警告:format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[3]’
printf("p4 + 2 = %s\n",p4 + 2); //p4 + 2 = GHIJ;
return 0;
}
/
#include <stdio.h>
int main()
{
int a[5][5];
int (* p)[4];
p = a;
printf("a_ptr = %p,p_ptr = %#p\n",&a[4][2],&p[4][2]); //a_ptr = 0xbfa7b680,p_ptr = 0xbfa7b670
printf("%p, %d\n",&p[4][2] - &a[4][2],&p[4][2] - &a[4][2]); //0xfffffffc, -4
return 0;
}