Pointer, gentle and dangerous-small talk C language (7)

Source: Internet
Author: User

[Mac-10.7.1 lion intel-based, GCC 4.2.1]

Q: What is a pointer?

A: One day, when you first arrived in Hefei, you wanted to go to a place, but the route was unfamiliar. Then I asked a passer-by WHERE IS ubento? The passer-by replied: Just go south. This answer is like a pointer, which tells you a direction. However, the value to the south is determined by the pointer type.

Q: When I see the const modifier, I don't know whether the pointer is a constant or whether the variable pointed to by the pointer is a constant?

A: Actually, it's very easy. You can do this by reading from right to left. Example:

#include <stdio.h>int main (int argc, const char * argv[]){    int i = 100;    const int *pi = &i;    *pi = 200;        return 0;}

Save as Const. C and use gcc-O const Const. C to compile:

A compilation error is displayed, indicating that PI is a pointer that cannot be changed to Data. According to the above principle of right-reading:

Const int * pi

Constant Integer Points to pi

Read as: PI points to an integer constant, that is, the variable that PI points to can be changed, but the value of the variable to which it points cannot be changed.

Of course, using the type method, const int * PI and INT const * Pi have the same meaning.

The following code is OK:

#include <stdio.h>int main(){    int i = 100, j = 200;    const int *pi = &i;    pi = &j;    return 0;}

Compile OK.

Another situation:

#include <stdio.h>int main(){    int i = 100, j = 200;    int *const pi = &i;    pi = &j;    return 0;}

Compile:

As you can see, a compilation error indicates that PI is read-only and cannot be changed. Then use the read method from right to left:

Int * const pi

Shaping points to constant pi

Read as: PI usually points to an integer

This also means that the PI value cannot be changed, but it does not mean that the data pointed to by PI cannot be changed.

#include <stdio.h>int main(){    int i = 100, j = 200;    int *const pi = &i;    *pi = j;    return 0;}

Compile the code above.

Q: I have read a lot of code that contains function pointers. What is its essence?

A: Its essence is a pointer. Theoretically, the address of the function can be calculated during the compilation period (of course, it may be located again when it is linked or running ). Let's take a look at a simple example:

#include <stdio.h>#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));int add(int a, int b){    return a + b;}int main(){    int (*func)(int, int) = add;    PRINT_D(func(1, 2))    return 0;}

Save as func_ptr.c and compile and run it:

Analyze the Code:

INT (* func) (INT, INT) indicates to declare a function pointer. Its parameters are two integers, And the return value is one integer. Where can it be reflected as a function pointer? It is the * number before func.

= Add; indicates that this pointer points to the Add function. The C language compilation principle is that the address of the current compilation status can be determined after the function is compiled. To be sure, let's look at the assembly code:

Gcc-s func_ptr.c is compiled (Part ):

_add:Leh_func_begin1:pushq%rbpLtmp0:movq%rsp, %rbpLtmp1:movl%edi, -4(%rbp)movl%esi, -8(%rbp)movl-4(%rbp), %eaxmovl-8(%rbp), %ecxaddl%ecx, %eaxmovl%eax, -16(%rbp)movl-16(%rbp), %eaxmovl%eax, -12(%rbp)movl-12(%rbp), %eaxpopq%rbpretLeh_func_end1:.globl_main.align4, 0x90_main:Leh_func_begin2:pushq%rbpLtmp2:movq%rsp, %rbpLtmp3:subq$16, %rspLtmp4:leaq_add(%rip), %raxmovq%rax, -16(%rbp)movq-16(%rbp), %raxmovl$1, %ecxmovl$2, %edxmovl%ecx, %edimovl%edx, %esicallq*%rax

We can see that _ add is a label in the assembly code, which means an address. Callq * % Rax can be seen, which is to call the Add function.

Q: Why don't I use & add when I use add to assign values to func? Isn't it the function address?

A: Yes. This is fine, but the function itself can be seen as an address. They work the same way.

#include <stdio.h>#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));#define PRINT_P(ptr)        printf("%10s is %p\n", (#ptr), (ptr));typedef int (*func)(int, int);int add(int a, int b){    return a + b;}int main(){    PRINT_P(add)    PRINT_P(&add)    return 0;}

Run:

Q: The writing of INT (* func) (INT, INT) is a bit complicated.

A: Yes. To avoid writing a lot of such code, you can use typedef to define a function pointer.

#include <stdio.h>#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));typedef int (*func)(int, int);int add(int a, int b){    return a + b;}int main(){    func add_func = add;    PRINT_D(add_func(1, 2))    return 0;}

Q: Can struct contain function pointers? What is the role of the function pointer here?

A: Yes, it can contain. The function pointer of a struct is generally used to serve the struct data. Its implementation can simulate the functions of classes in the object-oriented language. In fact, with pointers, the entire programming world has become very exciting, and many simulation methods are achieved through pointers.

#include <stdio.h>#include <string.h>#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));#define PRINT_S(str)        printf(#str" is %s\n", (str));typedef struct Student{    int     age;    char    name[32];    int     (*get_age)(struct Student *s);    void    (*set_age)(struct Student *s, int new_age);    char    *(*get_name)(struct Student *s);    void    (*set_name)(struct Student *s, char *new_name);}Student;int student_get_age(struct Student *s){    return s->age;}void    student_set_age(struct Student *s, int new_age){    s->age = new_age;}char    *student_get_name(struct Student *s){    return s->name;}void    student_set_name(struct Student *s, char *new_name){    memset(s->name, 0, sizeof(s->name));    strncpy(s->name, new_name, sizeof(s->name));}int main(){    Student s;    s.get_age = student_get_age;    s.set_age = student_set_age;    s.get_name = student_get_name;    s.set_name = student_set_name;    student_set_age(&s, 25);    student_set_name(&s, "xichen");    PRINT_D(student_get_age(&s))    PRINT_S(student_get_name(&s))    return 0;

Compile and run:

Q: It seems that there are many connections between the array and pointer. Why is the output value of the following code incorrect?

#include <stdio.h>#include <string.h>#definePRINT_D(intValue)printf(#intValue" is %d\n", (intValue));void    print_arr_size(int arr[3]){    PRINT_D(sizeof(arr))}int main(){    int arr[3] = {1, 2, 3};    print_arr_size(arr);    return 0;}

Running result:

A: This is because the array form as a parameter will be degraded into a pointer, that is to say, the parameter int arr [3] of the print_arr_size function is actually equivalent to int * arr, so sizeof (ARR) the value is the pointer size (the author's platform pointer size is 8 ).

Q: I often see void * in the function prototype. What exactly does it represent?

A: For example,

void*malloc(size_t);

Apply for a space and return the corresponding pointer. But what type of pointer is used? This function cannot be determined and needs to be determined by external callers. Therefore, void * can be considered as a general pointer, other types of pointers can be assigned to void * type pointers. In addition, void * type pointers can be converted to required pointers by force conversion. They can be interpreted using object-oriented ideas, void * is a base class, char *, int *, and so on.

char *p = (char *)malloc(32);

Example of converting other types of pointers to void:

#include <stdio.h>#definePRINT_D(intValue)printf(#intValue" is %d\n", (intValue));int main(){    int i = 1;    void    *p = &i;    PRINT_D(*(int *)p)    return 0;}

Of course, void * only indicates a general pointer. In the end, it is not clear about the type of the pointer. Therefore, you cannot directly operate on the data of the void * type variable.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.