为什么会这样:
struct test {
int a;
};
typedef struct test * PTR_TEST;
但如果您这样做,则会出现以下警告:useless storage class specifier in empty declaration
static struct test {
int a;
};
typedef struct test * PTR_TEST;
为什么会这样:
struct test {
int a;
};
typedef struct test * PTR_TEST;
但如果您这样做,则会出现以下警告:useless storage class specifier in empty declaration
static struct test {
int a;
};
typedef struct test * PTR_TEST;
文件file.h
中定义了以下函数:
static void fun(void)
{
printf("Hello world\n");
}
该文件file.c
包含以下代码,可以正常运行:
#include "file.h"
int main()
{
func();
return 0;
}
实际上问题是 - 为什么函数fun()
在头文件之外可见,如果它应该只在文件内部可见file.h
?
假设有一个包含一张照片卡的单页网站。用户已进入该站点并且什么都不做(不点击,不使用滚轮滚动)。一段时间后,网站上出现了第二张图片。
问题:如何使服务器发送的第二张(第三张等)照片卡出现在页面上,而不需要明确的客户端请求?
ps 如果不完全清楚这是什么意思,那么:例如,当用户在 VK 中收到消息时,会显示通知(在这种情况下,用户不必在站点上处于活动状态)。
有什么区别:
int fun(int ()) {
return 1;
}
和
int fun(int (*)()) {
return 1;
}
为了创建一个守护进程(至少在 Linux 上),必须采取一些步骤,我现在将对其进行描述。在问题的最后,如果有人明白,那么请回答,我将不胜感激。
1)您需要调用一个函数fork()
来创建子进程并终止父进程。这样做是为了让我们的子进程在后台混淆(如果错误,则正确)
if( (pid = fork()) < 0)
return -1;
else if(pid)
exit(0);
2)然后我们调用setsid()
创建新会话的函数。另外,调用进程成为组的leader,新会话的leader,没有控制终端。
if(setsid() < 0)
return -1;
"Разработка сетевых приложений" Стивенс У.Р
在我举这个例子的书中,作者再次调用该函数fork()
以确保守护程序在打开终端设备时不能自动获取控制终端。请注意,当父进程终止时(在我们的例子中первого дочернего процесса
),会向会话中的所有进程(包括我们的второму дочернему процессу
)发送一个信号SIGHUP
(当有人杀死终端,而不杀死终端窗口内运行的应用程序时,操作系统将信号发送给程序) ,我们需要忽略它。
3)我们用命令改变当前目录chdir("/");
4) 关闭文件描述符。作者是这样做的
for(i = 0; i < 64; i++)
close(i);
还有更多...我不会给出其余的代码,因为它与问题的本质无关,但是我之前指出的互联网上有一本书,您可以在其中找到完整的示例。
事实上,我的вопросы
:
1)这个问题可能看起来很傻,但我不太明白什么управляющий терминал
。是不是像下面的终端root
?请解释它是什么以及它的作用。
2)为什么需要更改当前目录?书上说的不多,我也不是很懂。
3)我们关闭负责的描述符是什么?他们应该完全关闭吗?
我在使用函数时遇到了困难getsockopt()
,更具体地说,在运行下面的示例时,我得到了不同的值:
int main(void){
int testtcp;
int val;
socklen_t len;
testtcp = socket(AF_INET, SOCK_STREAM, 0);
getsockopt(testtcp, SOL_SOCKET, SO_RCVBUF, &val, &len);
printf("%d %i\n", val, len);
}
当我运行此代码时,我得到0 0
, 或87380 4
. 请提示,用什么可以连接?
调用select()
如下所示的函数后:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
我们可以在句柄上调用一个宏FD_ISSET()
来检查标志(我们的句柄准备好了吗)
void FD_ISSET(int fd, fd_set *set);
FD_ISSET()
请告诉我,在为带有标志的描述符调用宏后,该标志在调用后是否降低?
函数select()
看起来像这样
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
我有几个问题:
1)我以某种方式模糊地想象它是如何工作的。如我错了请纠正我。假设,在调用这个函数之前,我们“调用”了宏
void FD_ZERO(fd_set *set);
这样就没有垃圾和宏
void FD_SET(int fd, fd_set *set);
表示我们感兴趣的描述符。然后我们调用函数本身并阻塞,直到我们的句柄之一准备好被读取或写入(取决于我们使用宏指定的内容)或直到计时器到期,或者直到“异常发生”。所以实际上是一个问题 - 功能是否被阻止?如果不难,那么请解释一下函数的原理。
2) 我们函数的第一个参数是一个整数,比任何集合中的最大文件描述符大一个。请告诉我,如果我只对一个描述符感兴趣 -5
我使用宏设置,如果我在描述符中写一些东西(然后按)FD_SET()
,函数会被中断吗?一般来说,我不清楚,该函数将仅“监视”描述符还是全部 from to ?0
enter
5
0
5
假设有一个程序,当接收到某个信号时,打印该信号的编号以及ID
发送该信号的进程。在代码中,一切看起来像这样:
用作函数的信号处理程序的函数sigaction()
void fun(int sig, siginfo_t *make, void *arg){
printf("Received signal: %d\n", sig);
printf("From process %u\n", make->si_pid);
printf("Done from function\n");
}
还有我自己main()
int main(void)
{
struct sigaction test;
memset(&test, 0, sizeof(test));
printf("I am process %i\n", getpid());
test.sa_sigaction = &fun;
test.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &test, NULL);
sleep(100);
printf("Done from main\n");
return 0;
}
该程序将使用一个信号SIGTERM
- 一个请求进程结束的信号。文末会写怎么看程序的输出,不过现在想问几个问题:
1)请告诉我,sigaction()
是否为该函数创建了一个单独的进程/线程?我只是不太明白为什么,当我在 main() 中调用这个函数时,它只在收到信号时才执行,而不是在我调用它时立即执行。
2)我不太明白 flag 的含义SIGINFO
,但是如果我不设置它,那么答案会有所不同。请解释它的用途(程序/用户)
3)为什么,当控制从一个函数返回到另一个sigaction()
函数main()
时,程序立即显示该短语Done from main
,而不是100
在调用函数后等待几秒钟过去sleep()
。而如果为 单独创建线程sigaction()
,那为什么sleep()
接收到信号后会被忽略
程序输出:运行这个程序并记住函数输出到printf()
终端的数字,然后打开另一个终端并在那里写入以下命令
kill -SIGTERM <pid>
,其中 pid 是您记住的数字。
ps linux下可以,windows下没试过
我显然不太明白它们是如何工作union
的Си
,所以请在下面的小代码中评论我的问题。(为了缩短代码,我只给出函数main()
)
int main(void)
{
int sockfd;
socklen_t size = 2000;
union {
struct sockaddr sa;
char mas[2000];
}un;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
getsockname(sockfd, (struct sockaddr*)un.mas,&size);
printf("%d\n\n", un.sa.sa_family);
return 0;
}
1)我什至没有填写结构struct sockaddr sa
,为什么它printf()
打印正确的答案?
2)如果我改写,答案将是错误的union
。struct
3) 如果变量不在union
or中struct
,则会弹出警告sa.sa_family’ is used uninitialized in this function
。
请帮我弄清楚
有一个函数pthread_create()
的模板如下所示:
int pthread_create(pthread_t *pth, pthread_attr_t *att, void * (*function)(void *), void *arg);
我对此功能有一些疑问:
1)在不同的来源中调用一个函数看起来不同,哪一个是正确的,有什么区别吗?
void * fun(void *arg){
int count = * (int *)arg;
printf("Thread %d\n", count);
pthread_exit(NULL);
}
int main(void)
{
pthread_t thread;
int count = 1;
pthread_create(&thread, NULL, fun, &count); // первый способ
pthread_create(&thread, NULL, &fun, &count); // второй способ
pthread_exit(NULL);
}
2)为什么,当我们将一个函数传递给pthread_create()
一个函数fun()
时,我们不传递任何参数给它?相反,我在某处读到fun()
第四个函数参数被传递给函数pthread_create()
,但我不明白这是如何完成的。
3)该函数pthread_create()
将指针作为第一个参数pthread_t *
,这样做是为了节省内存等,还是因为地址起着某种作用?只是下面的代码证明了地址无关紧要:
void * fun(void *arg){
int count = * (int *)arg;
printf("Thread %d\n", count);
pthread_exit(NULL);
}
int main(void)
{
int i = 0;
int *status;
while(i < 10){
pthread_t thread;
status = malloc(1);
*status = i++;
pthread_create(&thread, NULL, fun, (void *)status);
printf("%ld\n", thread);
}
在这里,10
线程被创建,并且y地址thread
没有改变。
对于那些了解网络编程的人,请到最后,有问题自己。对于其他人,我将在下面解释更多。
(虽然我的问题不是关于网络编程的,但我会使用这个主题的一个例子,以免提出问题时出错)
有一个函数返回指向结构的指针:
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list; // массив, содержащий адреса всех сетевых интерфейсов
};
struct hostent *gethostbyname(const char *host_name);
此外,还有一个我们稍后会用到的结构。
struct in_addr {
unsigned long s_addr;
};
以及我们也需要的功能
char *inet_ntoa(struct in_addr in) // конвертирует целочисленный тип в айпи-адрес стандартного вида (с точкой)
因此,我们的目标是找出主机的 ip,为此我们执行以下操作:
int main(void){
struct hostent *test; // указатель на структуру hostent
struct in_addr **making; // ?
int i = 0;
char buffer[17]; /* буфер для хранения айпи-адреса в стандартном виде */
test = gethostbyname("www.google.com"); /* теперь test - структура типа hostent */
making = (struct in_addr **) test->h_addr_list; // ?
for(i = 0; making[i] != NULL; i++){ // ?
strcpy( buffer, inet_ntoa(*making[i])); // ?
}
puts(buffer); // выводим наш айпи адрес в стандартном виде с точкой
return 0;
}
其实我的问题:
1) 如何正确阅读下面的条目?
struct in_addr **making;
指向结构的指针?
2)这里发生了什么?我们是否正在初始化指向指针的指针?然后怎样呢?
making = (struct in_addr **) test->h_addr_list;
3)making[i]
它是结构还是指针?还是指向结构的指针?
4) 函数接受的参数是inet_ntoa()
一个 struct 类型in_addr
。但是我还是不太明白记录- *making[i]
。她喜欢什么?
5) 为什么我们需要使用这个循环
for(i = 0; making[i] != NULL; i++){
strcpy( buffer, inet_ntoa(*making[i]));
}
不能这样写
strcpy( buffer, inet_ntoa(*making[0]));
因为我们仍然只取第一个地址
提前感谢那些回答或至少阅读的人
有一个用于网络编程的函数,它的模板如下所示:
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
/* sockfd - сокет, который будет использоваться для обмена данными с сервером */
/* serv_addr содержит указатель на структуру с адресом сервера */
/* addrlen - длина этой структуры */
sockaddr 结构本身如下所示:
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
对于 sockfd 我调用 socket() 函数
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Константа AF_INET соответствует Internet-домену */
/* SOCK_STREAM обозначает передачу потока данных с предварительной установкой соединения */
/* последний аргумент функции socket() обозначает выбор протокола, 0 - протокол выбирается по умолчанию */
对于 AF_INET 域,有一个如下所示的特殊结构:
struct sockaddr_in {
short int sin_family; // Семейство адресов
unsigned short int sin_port; // Номер порта
struct in_addr sin_addr; // IP-адрес
unsigned char sin_zero[8]; // "Дополнение" до размера структуры sockaddr
};
struct in_addr {
unsigned long s_addr;
};
在我的程序中,我使用这样的结构:
int main(void){
struct sockaddr_in test;
test.sin_family = AF_INET;
test.sin_port = htons( 80 ); /* преобразовывает число из порядка хоста в сетевой */
test.sin_addr.s_addr = inet_addr("77.37.252.217"); /* конвертирует айпи в формат long */
}
所以,现在我将调用 connect() 函数,我之前描述的模板
connect(sockfd, (struct sockaddr *)&test, sizeof(test))
实际上我的问题是 - 是否可以在 C 中将一个结构转换为另一个结构,就像我们在调用 connect () 函数时所做的那样?
ps我很抱歉我的问题延伸了这么多,只是我的良心不允许我在没有解释任何内容的情况下提出它。
ps2 如您所知,我目前正在学习网络编程,所以如果您有相关文献,所有内容都可以访问并清楚地解释,那么请在评论中指出这一点(俄语或英语 - 没关系)。提前致谢
我正在创建一个函数,其唯一参数是指向 int** 的指针。在函数体中,我创建了一个自动变量并用一些值初始化它。然后我将此变量的地址分配给我的指针。代码看起来像这样:
void function(int ** p){
int count = 5;
*p = &count;
}
在 main() 中,我创建了一个指向 int * 的指针并为其调用此函数,即:
int main(){
int * p = NULL;
function(&p);
printf("MAIN = %d\n\n", *p); /* выводит 5 */
return 0;
}
还有一个问题——为什么线程退出函数后count变量内存中的数据没有被销毁?任何存储类的内存中的数据是否存在于整个程序的执行过程中?
假设我在 main() 中创建了一个指针数组,稍后我在该数组下分配内存并使用 fgets() 函数对其进行初始化。
int main(void){
char *p[5];
............
/* инициализация */
}
然后我想对给定的指针数组进行排序并调用 sort() 函数。为了不意外更改指针数组中的数据,我将排序函数的参数设为const,即:
void sorting(const char **p){
/* функция сортировки указателей */
}
但是,从 main() 调用此函数时,出现错误
int main(void){
.............
.............
sorting(p);
}
警告:
从不兼容的指针类型 [-Wincompatible-pointer-types] 排序(p)传递“排序”的参数 1;
预期为 'const char **' 但参数的类型为 'char **'
无效排序(const char **p){
据我所知,const 值可以用 NOT const 值初始化,但我读这个只是为了指针。请告诉我如何解决这个问题?
我遇到了一个我有几个问题的代码,如果你回答,我将不胜感激
#include <stdio.h>
#include <stdlib.h>
int isOdd(int a) {
return (a % 2 != 0);
}
unsigned int filter(int *arr, unsigned size, int (*pred)(int), int** out) {
unsigned i;
unsigned j;
*out = (int*) malloc(sizeof(int)*size);
for (i = 0, j = 0; i < size; i++) {
if (pred(arr[i])) {
(*out)[j] = arr[i];
j++;
}
}
*out = (int*) realloc(*out, j*sizeof(int));
return j;
}
int main () {
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
unsigned i;
unsigned size;
int *aOdd = NULL;
size = filter(a, 10, isOdd, &aOdd);
for (i = 0; i < size; i++) {
printf("%d ", aOdd[i]);
}
}
问题 #1:为什么需要这种显式转换?
*out = (int*) malloc(sizeof(int)*size);
*out = (int*) realloc(*out, j*sizeof(int));
如果我没记错的话,它们是多余的。
问题 #2:我用感叹号突出显示的行中发生了什么?
unsigned int filter(int *arr, unsigned size, int (*pred)(int), int** out) {
unsigned i;
unsigned j;
*out = (int*) malloc(sizeof(int)*size); /* !!!!!!!!!! */
for (i = 0, j = 0; i < size; i++) {
if (pred(arr[i])) {
(*out)[j] = arr[i]; /* !!!!!!!!!! */
j++;
}
}
*out = (int*) realloc(*out, j*sizeof(int)); /* !!!!!!!!!! */
return j;
}
问题#3:以这种方式实现问题#2中的函数会不会更容易(仅通过指针,而不是通过指向指针的指针)
unsigned int filter(int *arr, unsigned size, int (*pred)(int), int* out) {
unsigned i;
unsigned j;
for (i = 0, j = 0; i < size; i++) {
if (pred(arr[i])) {
*(out + j) = arr[i];
j++;
}
}
return j;
}
问题#2 中的功能和问题#3 中的功能之间是否存在显着差异甚至优势?
如果您能理解不完整的代码,请解释我用感叹号标记的行中发生的情况
#include <stdio.h>
void quicksort(int (*comp)()){
printf("lalal\n");
}
int first()
{
return 1;
}
int second(){
return 1;
}
int main()
{
int a;
a = getchar();
quicksort((int (*)()(a ? first : second)); /* !!!!!! */
return 0;
}
在我看来,正在创建指向其中一个函数的指针。其中一个选项是这样的(如果我错了,请解释会发生什么)
quicksort( int (*first)())
我必须马上说我提供的代码不完整。如果您不理解我的问题的本质,并且原因是“代码不完整”,那么最后我将提供一个完整代码示例的链接。
#include <stdio.h>
void dbleInt(void *a) {
*((int*) a) *= 2;
}
void dbleDouble(void *a) {
*((double*) a) *= 2.0;
}
void map(void *arr, unsigned num, size_t size, void (*fun)(void *)) {
unsigned i;
char *ptr = (char*) arr;
for (i = 0; i < num; i++) {
fun((void*) (ptr + i*size)); /* !!!!!! */
}
}
int main () {
return 0;
}
给定行
fun((void*) (ptr + i*size));
我会这样写
fun(ptr + i*size);
正确的书写方式是什么,这两个条目之间有区别吗?
ps 3 计数示例从开始https://learnc.info/c/function_pointers.html
为什么它有效?
#include <stdio.h>
int main(){
int *p1[1] = {2018};
char *p2[1] = {"abcd"};
p1[0] = p2[0];
printf("%s\n\n", p1[0]); /* выводит abcd */
return 0;
}
我们正在创建一个包含一个元素的数组,它是一个指向 int 的指针。如果有强制类型转换为 char*,那么为什么会在不丢失信息的情况下发生这种情况?
请解释这两个记录之间是否有区别,如果有,那是什么?
#include <stdio.h>
int sum(int a, int b){
return a+b;
}
main(){
int (*fun)(int , int) = NULL;
fun = sum;
printf("%d\n\n", fun(12,14));
printf("%d\n\n",(*fun)(12,14));
return 0;
}