指針&數組&字符串&結構體

1.指針的定義

指針就是內存地址,指針變量就是存儲地址的變量
聲明:數據類型: *指針變量的名字
int * p;
初始化:int *p = NULL;//空,0.0 \0 空指針

    int i =10;
    int *p;
    p = &i;
    printf("addr: &i=%p p=%p\n",&i, p);
    printf("value: i=%d *p=%d\n",i, *p);
指行結果:
addr: &i=0x7fff2d938e9c p=0x7fff2d938e9c
value: i=10 *p=10

2.指針作爲返回值

指針用作函數的返回值,表示返回一個地址
注意:不要返回自動變量的地址,自動變量在函數結束後使用的內存會被釋放

int *test(int n){
    int *p = &n;
    return p;
}

3.指針作爲函數的參數

函數可以接受一個地址作爲參數,函數可以修改實參的值,因爲指向地址的內容被修改了.

void swap(int *a,int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

4.字符串的表現形式

在C語方中,沒有string類型
字面值常量:”abcdef”以’\0’結束,存在於全局區,不可以改變
char arr[]:表示字符串類型的變量,後面加’\0’,存在於內存中函數棧,值可以改變
char * 指針存儲地址,可以指向字面值,也可以指向char數組裏面的無素

5.操作字符串的函數庫

位於string.h裏,在linux內核中源碼實現存在於lib/string.c

/**
 * strcpy - Copy a %NUL terminated string
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 */
char *strcpy(char *dest, const char *src)
{
    char *tmp = dest;

    while ((*dest++ = *src++) != '\0')
        /* nothing */;
    return tmp;
}

/**
 * strcat - Append one %NUL-terminated string to another
 * @dest: The string to be appended to
 * @src: The string to append to it
 */

char *strcat(char *dest, const char *src)
{
    char *tmp = dest;

    while (*dest)
        dest++;
    while ((*dest++ = *src++) != '\0')
        ;
    return tmp;
}
/**
 * strlen - Find the length of a string
 * @s: The string to be sized
 */
size_t strlen(const char *s)
{
    const char *sc;

    for (sc = s; *sc != '\0'; ++sc)
        /* nothing */;
    return sc - s;
}
/**
 * strcmp - Compare two strings
 * @cs: One string
 * @ct: Another string
 */

int strcmp(const char *cs, const char *ct)
{
    unsigned char c1, c2;

    while (1) {
        c1 = *cs++;
        c2 = *ct++;
        if (c1 != c2)
            return c1 < c2 ? -1 : 1;
        if (!c1)
            break;
    }
    return 0;
}

6.結構體

結構體:不同類型數據的集合
成員可以具有不同的類型
每個成員都有名字,通過名字來訪問成員
使用一個結構體變量之前,必須先進行類型定義
typedef:給類型起別名
typedef struct
{
成員列表;
}別名;

#include <stdio.h>
#include <string.h>
typedef struct{
    int id;
    char name[20];
    char sex;
    int age;
} student;

int main(){

    student s;
    s.id = 1;
    strcpy(s.name, "bshui");
    s.sex = 'M';
    s.age = 18;
    printf("id:%d name:%s sex:%c age:%d\n",s.id,
                s.name, s.sex, s.age);

    return 0;
}

運行結果:
id:1 name:bshui sex:M age:18

7.結構體作爲函數的參數與返回值

如果使用結構體作爲函數的參數與返回值會佔用大量的內存,會消耗大量的時間
一般使用結構體指針作爲函數的參數和返回值,提高程序的效率

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
    int id;
    char name[20];
    char sex;
    int age;
} student;
void show_info(student *s);
int main(){

    student *s = (student *)malloc(sizeof(student));

    s->id = 1;
    strcpy(s->name, "bshui");
    s->sex = 'M';
    s->age = 18;

    show_info(s);

    return 0;
}

void show_info(student *s){

    printf("id:%d name:%s sex:%c age:%d\n",s->id,
                s->name, s->sex, s->age);
}

運行結果:
id:1 name:bshui sex:M age:18

8.結構體的對齊與補齊

對齊:內存分配將結構體中的成員分配到內存的邊界上,方便訪問,每個成員都是從自身長度的整數倍開始存放
補齊:整個的結構體長度必須保持爲內部最長成員的整數倍

#include <stdio.h>
#include <stdlib.h>
typedef struct{
        int i; // 4
        short sh;//2
        char c; //1 
        double d; //8

} s;

typedef struct{
    char a; //2
    short b; //2
    char d; //2
} t;
int main(){

    s s1;
    t t1;
    //對齊
    printf("t:%ld\n", sizeof(t1));
    //補齊
    printf("s:%ld\n",sizeof(s1));



    return 0;
}
執行結果:
t:6
s:16

9.聯合體

可以有多個不同類型的成員組成
通過成員的名字訪問成員
所有成員共用起始地址相同的一段內存

大端:低位字節存儲高位數據
小端:低位字節存儲低位數據

#include <stdio.h>
int main(){

    union{
        int i;
        char c;
    }u;

    u.i = 1;
    if(u.c==1)
      printf("little end\n");
    else
      printf("big end\n");

    return 0;
}

10.指針類型區分

int i:定義一個整型變量
int *q; q是一個指向整型變量的指針
int a[n]; a數組,包含n個整型的元素
int *q[n]; q數組,包含n個元素每個元素都是指向整型數據的指針
int (*q)[n]; q指針,指向一個數組,可以包含n個整型元素
int f(); f函數,返回值類型爲int
int *f(); f函數,返回值類型指向整型數據的指針
int (*f)(); f函數指針,指向一個函數,函數返回值爲int
itn **q; q指針,指向一個指針

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章