вывести значение пустого указателя - PullRequest
1 голос
/ 24 апреля 2020

Это рис. 11.3 в книге Расширенное программирование в UNIX Окружающей среде

#include <pthread.h>

#include "apue.h"

void* thr_fn1(void* arg) {
    printf("thread 1 returning\n");
    return ((void*)1);
}

void* thr_fn2(void* arg) {
    printf("thread 2 exiting\n");
    pthread_exit((void*)2);
}

int main(void) {
    int err;
    pthread_t tid1, tid2;
    void* tret;

    err = pthread_create(&tid1, NULL, thr_fn1, NULL);
    if (err != 0) err_exit(err, "can't create thread 1");
    err = pthread_create(&tid2, NULL, thr_fn2, NULL);
    if (err != 0) err_exit(err, "can't create thread 2");

    err = pthread_join(tid1, &tret);
    if (err != 0) err_exit(err, "can't join with thread 1");
    printf("thread 1 exit code %ld\n", (long)tret);

    err = pthread_join(tid2, &tret);
    if (err != 0) err_exit(err, "can't join with thread 2");
    printf("thread 2 exit code %ld\n", (long)tret);
    exit(0);
}

Я был озадачен тем, что не могу набрать пустой указатель на указатель на long и разыменование это

printf("thread 1 exit code %ld\n", *(long *)tret);

почему мы можем привести тип tret к long и получить правильное значение, которое мы хотим здесь

printf("thread 1 exit code %ld\n", (long)tret);

какой тип tret здесь?

Я показываю Легкий случай из GeeksforGeeks, чтобы напечатать значение пустого указателя ниже

#include<stdio.h> 
int main() 
{ 
    int a = 10; 
    void *ptr = &a; 
    printf("%d", *(int *)ptr); 
    return 0; 
} 

В чем разница между двумя кодами выше?

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

Я думаю, это потому, что согласно руководству pthread_join, оно хранит возвращаемое значение потока, а не адрес памяти: как вы можете видеть в функциях thr_fn1 и 2, возвращаемое значение равно (void *) 1 и ( void *) 2.

Разыменование указателя не имеет смысла, поскольку нас интересует его значение, а не адрес, на который он указывает.

Во втором случае используется этот метод, поскольку ptr на самом деле является памятью. адрес.

1 голос
/ 24 апреля 2020

Меня смутило то, что я не могу типизировать пустой указатель на указатель на long и разыменовать его

printf("thread 1 exit code %ld\n", *(long *)tret);

, если вы сделаете это, вы разыменуете адрес, но этот адрес равен 1 или 2, чей адрес, скорее всего, неправильный, и даже если его нет, вы не можете предположить, что они содержат.

почему мы можем типизировать tret в long и получить правильное значение, которое мы хотим здесь

printf("thread 1 exit code %ld\n", (long)tret);

Какой тип трета здесь?

Трэт является void *, а ваш thr_f возвращает a void * тоже, поэтому правильный способ сделать это:

printf("thread 1 exit code %p\n", tret);

иначе вы предполагаете, что long и void* имеют одинаковый размер

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...