1. 程式人生 > >是否瞭解printf("%s",....)與printf("%c",...)的區別,指標的強制轉換成一維指標和二維指標甚至多維指標時如何正確使用

是否瞭解printf("%s",....)與printf("%c",...)的區別,指標的強制轉換成一維指標和二維指標甚至多維指標時如何正確使用

程式碼1: 

#include <stdio.h>

#define va_list void*
#define va_start(arg, start)   arg = (va_list)( ((char*)&start) + sizeof(start) )
void print( char* format, ...)
{
	va_list arg;
    printf("%d\n", *(int*)(va_start(arg, format)) );
}


void main()
{
  char *p = "123";
  print("%s",4);
}

arg=(va_list)( ((char*)& format) + sizeof(format) )// sizeof(format)4位元組,(char*)的作用只加1位元組

比如& format的地址為100,加上(char*)” ((char*)& format) + sizeof(format)”的地址為104

*(int*)(va_start(arg, format))的解析//void*型別轉換為(int *)一維指標,指向((char*)&format)+ sizeof(format)這個地址,通過*取得裡面的值

程式碼輸出結果:4

Printf(“%s”,…)和

printf(“%c”,…)的區別

Printf(“%s”,資料的記憶體地址)

例如:

char a[5] = "123";

printf("%s\n", a );

Printf(“%c”,)

例如:

char a[5] = "123";

printf("%s\n", *a );

程式碼2: 

#include <stdio.h>

#define va_list void*
#define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start))//
void print( char* format, ...)
{
	va_list arg;
	char ch;
	char *str;
    printf("%s\n", *(int*)(va_start(arg, format)) );
}


void main()
{
  char *p = "123";
  print("%s",p);//與程式碼1不同的地方
}

此時,值4變為了字串“123”的首地址,在通過%s打印出來

程式碼輸出結果:123

程式碼3:

#include <stdio.h>

#define va_list void*
#define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start))//
void print( char* format, ...)
{
	va_list arg;
	char ch;
	char *str;
    printf("%s\n", *(int**)(va_start(arg, format)) );//不同於程式碼2的地方
}


void main()
{
  char *p = "123";
  print("%s",p);
}

通過對程式碼2和程式碼3的比較,可以發現,都是對(va_start(arg, format))裡面的值進行解析,卻有不同的方式。程式碼3此時利用(int**)一個二維指標指向“123”的首地址,*(int**)取到“123”的首地址,**(int**)取到首地址裡面的值1.這時候需要用printf("%c\n", **(int**)(va_start(arg, format)) )列印裡面的值而不是通過“%s”來列印

執行結果:123

程式碼4:

#include <stdio.h>

#define va_list void*
#define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start))//
void print( char* format, ...)
{
	va_list arg;
	char ch;
	char *str;
    printf("%s\n", *(int*)(va_start(arg, format)) );//不同於程式碼3的地方
}


void main()
{
  char *p = "123";
  print("%s",p);
}

對比程式碼4與程式碼3,此時我們把(va_start(arg, format))裡面的值通過(int *)解析為一維指標,通過*(int*)取得“123”的首地址,因為是一維指標所以不能使用**(int*)(va_start(arg, format))取得裡面的值1

執行結果:123

程式碼5: 

#include <stdio.h>

#define va_list void*
#define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start))//
void print( char* format, ...)
{
	va_list arg;
	char ch;
	char *str;
    printf("%s\n", *(int****)(va_start(arg, format)) );//與程式碼3,4不同的地方
}


void main()
{
  char *p = "123";
  print("%s",p);
}

執行結果:123

va_start(arg, format)裡面的值的值解析為5維指標,只不過可以對裡面的值進行5次解引用,這時可以視情況而使用,例如

三維指標指向的使用

#include <stdio.h>

#define va_list void*
#define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start))//
void print( char* format, ...)
{
	va_list arg;
	char ch;
	char *str;
        printf("%s\n", **(int***)(va_start(arg, format)) );//指向三維指標
	printf("%c\n", ***(int***)(va_start(arg, format)) );//取最後的值1
}


void main()
{
  char *str = "123";
  char **p = &str;
  print("%s",p);
}

執行結果:123

                   1

*(int***):取得str變數的地址

**(int***):取得“123”的首地址

***(int***):值1

總結:任何地址都可以轉換成多維指標,例如

int a;

(int *)&a;//轉換成一維指標

(int **)&a//轉換成二維指標

(int ***)&a;//轉換成三維指標

int a[3] = {0};

(int *)a;//轉換成一維指標

(int **)a;//轉換成二維指標

並分析指向記憶體塊中的值通過*解引用取出來

如有不當之處,懇請指出一共探討

參考連結:

陣列指標