Clarifying Doubts in C Language Learning

2020年3月5日 3375点热度 1人点赞 0条评论
内容目录

%#

%# is used for formatted output, typically in the form %#p.
%x is used to display in hexadecimal format, but the output format may vary depending on the environment.
%p displays a hexadecimal representation of a system address as an integer within the range of valid values. The number of digits printed corresponds to the address size: 8 digits for a 32-bit system and 16 digits for a 64-bit system. If there are fewer than 8 digits, it automatically pads with 0s;
for example, for an int of 4 bytes, %p prints the value in a 32-bit binary representation, padding with 0s as needed. It is mainly used for outputting addresses and pointers.
%# indicates formatted output, automatically adding 0x for hexadecimal representations.

Size of Pointer Addresses

Pointer addresses are stored using 4 bytes.
Types like char *, int *, double *, etc., are all pointer types that occupy four bytes!

(char*)

This denotes converting a value to a pointer of type char.
This is a typecast and does not imply special meaning; it has the same significance as the assignment in the following example:

char a = '6';
int b = (int)a;

Example

#include <stdio.h>

int main(void)
{
    char a = 'a';
    int b = (int)&a; /* Assigning the address as a value to b, pointers are stored in 4 bytes */
    printf(b);

    char *p;
    p = (char *)b;               /* Converting value to address form */

    printf(*p);

    return(0);
}

while({expression})

In C, there is no boolean type, https://www.whuanle.cn/archives/738.
A while condition continues to run while it is true (or 1, or non-zero). It stops when encountering false, 0, '\0', etc.

whille(a > b)
while(i)
while(2)

char *p vs char* p

Both essentially define a pointer. However, there is a distinction when defining multiple variables.
Using char* indicates that all declared variables are pointers; for example:

    char* a, b, c;

In the following example, only j is a pointer variable while the others are char variables.

char *j, p, k;

However, combining normal and pointer variables in the same declaration can lead to ambiguity, so it is generally advisable to declare them on separate lines.
If necessary to declare them together, the following format is often used:

    char l, m, *n;

For function declarations, the position of the * is not significant.

char* test()
char *test()

malloc and calloc

Both are used for memory allocation and are defined in the header file stdlib.h.
malloc does not initialize the allocated memory, leaving the contents of all bytes with random values from before allocation.
On the other hand, calloc initializes all bytes to zero while allocating memory.
In newer C language standards, both malloc and calloc return a pointer of type void, meaning the returned address can be assumed to point to any valid data type.

Typically, pointers are defined with data types, such as char *p or int *i.
When using malloc and calloc, they can be converted to any type of pointer.

The following is incorrect usage due to malloc returning a void pointer:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char *p;
    p = malloc(200);
    gets(p);
    printf(p);
    free(p);
    return 0;
}

Therefore, to allocate memory and receive the pointer, the correct approach is:

    p = (char *)malloc(200);

Another issue is that memory allocation may not always succeed; if it fails, it returns NULL.

Thus, it should be written as follows:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char* p;
    p = (char*)malloc(200);
    if (p == NULL)
    {
        printf("Allocation failed");
        exit(1);
    }
    gets(p);
    printf(p);
    free(p);
    return 0;
}

Pointer Initialization

There are two methods for initializing pointers: using the address of an existing variable or using dynamically allocated memory.
Example

    char a = 'a';
    // Method 1
    char* p = &a;
    // Method 2
    p = (char*)malloc(200);

Pointer Variables Are Also Variables

Pointer variables are also variables and have scopes.

#include <stdio.h>

char* test(char* p) {
    printf("Address of p %#p \n", &p);
    return p;
}

int main() {

    char a = 'a';
    char* p1 = &a;
    printf("Address of p1 %#p \n", &p1);

    char* p2 = test(p1);
    printf("Address of p2 %#p \n", &p2);
    return 0;
}

The output is as follows:

Address of p1 000000C166F5FA08
Address of p 000000C166F5F9C0
Address of p2 000000C166F5FA28

We can see that the addresses of each p are different. Pointer variables also have scopes.

Big Endian and Little Endian Storage

Words and bytes:
A byte consists of 8 bits, which is nearly universal across all computers.
In terms of CPU bitness, the number of bits it can process at one time is translated into byte size, referred to as the full word size. There are also double words and half-words:
in a 64-bit computer, a full word is 8 bytes (64 bits). A double word is 16 bytes, and a half-word is 4 bytes.
We can understand it this way: in a 32-bit system, a full word is 4 bytes, a half-word is 2 bytes, and a double word is 8 bytes.
A short is a half-word (2 bytes), long is a full word (4 bytes), and double is a double word.

Generally, for a byte, the high-order bits are on the left and the low-order bits on the right. For multiple bytes, the high-order byte is on the left and the low-order byte on the right.

In the case of registers and memory, if both have high-order bits on the left and low-order bits on the right, it is referred to as little-endian storage. When a long is converted to an int, only the low-order 2/4 bytes are received by the int. In a union, variables share memory and may affect the low-order bytes.

Void Pointers

Just like C# or Java's object type.

object a = new MyClass();
int b = (MyClass)a.Test();

A void pointer can point to any type of variable address.
However, to use the value at this address, it must first be cast to the corresponding pointer type.

#include <stdio.h>

int main() {

    char a = 'a';
    int b = 0;

    void* p = &a;
    printf("%d", *(char*)p);

    p = &b;
    printf("\n");
    printf("%d", *(int*)p);
}

痴者工良

高级程序员劝退师

文章评论