Why define INT_MIN (-INT_MAX - 1)

本文探讨了C语言中INT_MIN被定义为(-INT_MAX - 1)而非直接定义为-2147483648的原因。-2147483648在某些情况下可能超出int范围,导致未定义行为。通过示例代码展示了不同平台上的运行结果,解释了-INT_MAX - 1确保了INT_MIN为最小整数值。

C语言定义INT_MIN和INTMAX如下:

#define INT_MAX     2147483647

#define INT_MIN      (-INT_MAX - 1)

为什么不直接定义INT_MIN为-2147483648呢?

如果你运行如下代码:

if (-2147483648 > 0)
    printf(“TRUE”);
else
    printf(“FALSE”);
/* RINEX观测值文件读取程序 来源:https://blog.youkuaiyun.com/why1472587/article/details/127514022 本程序用于读取RINEX 2.1.1格式的观测值文件(O文件) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define MAXRINEX 84 // 最大读取字符数 // 观测值头文件结构体 typedef struct obs_head { double ver; // RINEX文件版本号 char type[30]; // 文件类型 double apX; // 测站近似位置X double apY; // 测站近似位置Y double apZ; // 测站近似位置Z double ANTH; // 天线高 double ANTdeltaE; // 天线中心东向偏移量 double ANTdeltaN; // 天线中心北向偏移量 int WAFL1; // L1载波波长因子 int WAFL2; // L2载波波长因子 int WAFflag; int obstypenum; // 观测值类型数量 char obstype[15]; // 观测值类型列表 double interval; // 观测值历元间隔 int f_y; // 第一个观测记录的年 int f_m; // 第一个观测记录的月 int f_d; // 第一个观测记录的日 int f_h; // 第一个观测记录的时 int f_min; // 第一个观测记录的分 double f_sec; // 第一个观测记录的秒 char tsys[5]; // 时间系统 } obs_head, *pobs_head; // 观测值历元数据结构体 typedef struct obs_epoch { int y, m, d, h, min; double sec; int p_flag; // 历元标志 int sat_num; // 当前历元观测到的卫星数量 int sPRN[24]; // 卫星PRN列表 } obs_epoch, *pobs_epoch; // 观测值数据结构体 typedef struct obs_body { double obs[24][15]; // 观测值 [卫星][观测类型] } obs_body, *pobs_body; // 函数声明 extern int get_epochnum(FILE* fp_obs); extern void read_h(FILE* fp_obs, pobs_head obs_h); extern void read_b(FILE* fp_obs, pobs_epoch obs_e, pobs_body obs_b, int type); extern void display_header(pobs_head obs_h); extern void display_epoch_data(pobs_epoch obs_e, pobs_body obs_b, int epochnum, int obstypenum); // 将字符串转换为浮点数 static double strtonum(const char* buff, int i, int n) { double value = 0.0; char str[256] = { 0 }; char* p = str; if (i < 0 || (int)strlen(buff) < i || (int)sizeof(str) - 1 < n) { return 0.0; } for (buff += i; *buff && --n >= 0; buff++) { *p++ = ((*buff == ‘D’ || *buff == ‘d’) ? ‘e’ : *buff); } *p = ‘\0’; return sscanf(str, “%lf”, &value) == 1 ? value : 0.0; } // 获取O文件历元数 extern int get_epochnum(FILE* fp_obs) { int n = 0; // 记录历元数 int satnum = 0; // 记录每个历元的卫星数 char flag; // 存放卫星标志符号’G’ char buff[MAXRINEX];// 存放读取的字符串 while (fgets(buff, MAXRINEX, fp_obs)) { satnum = (int)strtonum(buff, 30, 2); strncpy(&flag, buff + 32, 1); if (flag == ‘G’) { n++; } // 当卫星数超过12个时,一行存不下会转到下一行 if (flag == ‘G’ && satnum > 12) { n–; } } return n; } // 读取O文件数据头 extern void read_h(FILE* fp_obs, pobs_head obs_h) { char buff[MAXRINEX] = { 0 }; char* lable = buff + 60; int i = 0; while (fgets(buff, MAXRINEX, fp_obs)) { if (strstr(lable, “RINEX VERSION / TYPE”)) { obs_h->ver = strtonum(buff, 0, 9); strncpy(obs_h->type, buff + 20, 30); continue; } else if (strstr(lable, “APPROX POSITION XYZ”)) { obs_h->apX = strtonum(buff, 0, 14); obs_h->apY = strtonum(buff, 0 + 14, 14); obs_h->apZ = strtonum(buff, 0 + 14 + 14, 14); continue; } else if (strstr(lable, “ANTENNA: DELTA H/E/N”)) { obs_h->ANTH = strtonum(buff, 0, 14); obs_h->ANTdeltaE = strtonum(buff, 14, 14); obs_h->ANTdeltaN = strtonum(buff, 14 + 14, 14); continue; } else if (strstr(lable, “WAVELENGTH FACT L1/2”)) { obs_h->WAFL1 = (int)strtonum(buff, 0, 6); obs_h->WAFL2 = (int)strtonum(buff, 6, 6); obs_h->WAFflag = (int)strtonum(buff, 6 + 6, 6); continue; } else if (strstr(lable, “# / TYPES OF OBSERV”)) { obs_h->obstypenum = (int)strtonum(buff, 0, 6); if (obs_h->obstypenum <= 9) { for (i = 0; i < obs_h->obstypenum; i++) { strncpy(&(obs_h->obstype[i]), buff + 10 * i, 2); } } else if (obs_h->obstypenum > 9) { for (i = 0; i < 9; i++) { strncpy(&(obs_h->obstype[i]), buff + 10 * i, 2); } fgets(buff, MAXRINEX, fp_obs); for (i = 0; i < obs_h->obstypenum - 9; i++) { strncpy(&(obs_h->obstype[i + 9]), buff + 10 * i, 2); } } continue; } else if (strstr(lable, “INTERVAL”)) { obs_h->interval = strtonum(buff, 0, 11); continue; } else if (strstr(lable, “TIME OF FIRST OBS”)) { obs_h->f_y = (int)strtonum(buff, 0, 6); obs_h->f_m = (int)strtonum(buff, 6, 6); obs_h->f_d = (int)strtonum(buff, 6 + 6, 6); obs_h->f_h = (int)strtonum(buff, 6 + 6 + 6, 6); obs_h->f_min = (int)strtonum(buff, 6 + 6 + 6 + 6, 6); obs_h->f_sec = strtonum(buff, 6 + 6 + 6 + 6 + 6, 6); strncpy(obs_h->tsys, buff + 6 + 6 + 6 + 6 + 6 + 18, 3); continue; } else if (strstr(lable, “END OF HEADER”)) break; } } // 读取O文件数据块 extern void read_b(FILE* fp_obs, pobs_epoch obs_e, pobs_body obs_b, int type) { int n = 0; // 历元数 int i, j, k; // 循环变量 char buff[MAXRINEX] = { 0 }; char flag = { 0 }; while (fgets(buff, MAXRINEX, fp_obs)) { // 检查是否为历元开始行 if (strlen(buff) < 30) continue; // 读取历元时间 obs_e[n].y = (int)strtonum(buff, 1, 2) + 2000; obs_e[n].m = (int)strtonum(buff, 4, 2); obs_e[n].d = (int)strtonum(buff, 7, 2); obs_e[n].h = (int)strtonum(buff, 10, 2); obs_e[n].min = (int)strtonum(buff, 13, 2); obs_e[n].sec = strtonum(buff, 15, 11); obs_e[n].p_flag = (int)strtonum(buff, 28, 1); obs_e[n].sat_num = (int)strtonum(buff, 29, 3); // 限制卫星数量 if (obs_e[n].sat_num < 0 || obs_e[n].sat_num > 24) { obs_e[n].sat_num = 0; continue; } strncpy(&flag, buff + 32, 1); // 读取卫星PRN if (obs_e[n].sat_num <= 12 && flag == ‘G’) { for (i = 0; i < obs_e[n].sat_num && i < 24; i++) { obs_e[n].sPRN[i] = (int)strtonum(buff, 33 + 3 * i, 2); } } else if (obs_e[n].sat_num > 12 && flag == ‘G’) { for (i = 0; i < 12 && i < 24; i++) { obs_e[n].sPRN[i] = (int)strtonum(buff, 33 + 3 * i, 2); } if (fgets(buff, MAXRINEX, fp_obs)) { for (i = 0; i < obs_e[n].sat_num - 12 && i < 12; i++) { obs_e[n].sPRN[i + 12] = (int)strtonum(buff, 33 + 3 * i, 2); } } } // 读取观测数据 for (i = 0; i < obs_e[n].sat_num && i < 24; i++) { int lines = (int)ceil((double)type / 5.0); for (j = 0; j < lines && j < 3; j++) { if (!fgets(buff, MAXRINEX, fp_obs)) break; int values_per_line = (j == lines - 1) ? (type % 5 ? type % 5 : 5) : 5; for (k = 0; k < values_per_line && k < 5; k++) { if (16 * k + 16 <= MAXRINEX) { obs_b[n].obs[i][k + 5 * j] = strtonum(buff, 16 * k, 16); } } } } n++; } } // 显示文件头信息 extern void display_header(pobs_head obs_h) { printf(“=== RINEX文件头信息 =\n"); printf(“版本号: %.2f\n”, obs_h->ver); printf(“文件类型: %.30s\n”, obs_h->type); printf(“测站近似坐标: X=%.3f, Y=%.3f, Z=%.3f\n”, obs_h->apX, obs_h->apY, obs_h->apZ); printf(“天线高: %.3f\n”, obs_h->ANTH); printf(“天线偏移: E=%.3f, N=%.3f\n”, obs_h->ANTdeltaE, obs_h->ANTdeltaN); printf(“观测值类型数量: %d\n”, obs_h->obstypenum); printf(“观测值类型: “); for (int i = 0; i < obs_h->obstypenum; i++) { printf(”%c%c “, obs_h->obstype[i2], obs_h->obstype[i2+1]); } printf(”\n采样间隔: %.1f秒\n”, obs_h->interval); printf(“起始时间: %04d-%02d-%02d %02d:%02d:%.0f\n”, obs_h->f_y, obs_h->f_m, obs_h->f_d, obs_h->f_h, obs_h->f_min, obs_h->f_sec); printf(“时间系统: %.3s\n”, obs_h->tsys); printf("======================\n\n”); } // 显示历元数据 extern void display_epoch_data(pobs_epoch obs_e, pobs_body obs_b, int epochnum, int obstypenum) { printf(“=== 历元数据摘要 ===\n”); printf(“总历元数: %d\n”, epochnum); for (int n = 0; n < epochnum && n < 3; n++) { // 只显示前3个历元 printf(“\n历元 %d:\n”, n+1); printf(“时间: %04d-%02d-%02d %02d:%02d:%.0f\n”, obs_e[n].y, obs_e[n].m, obs_e[n].d, obs_e[n].h, obs_e[n].min, obs_e[n].sec); printf(“卫星数量: %d\n”, obs_e[n].sat_num); printf(“卫星列表: “); for (int i = 0; i < obs_e[n].sat_num; i++) { printf(“G%02d “, obs_e[n].sPRN[i]); } printf(”\n”); // 显示第一个卫星的前几个观测值 if (obs_e[n].sat_num > 0) { printf(“G%02d观测值: “, obs_e[n].sPRN[0]); for (int j = 0; j < obstypenum && j < 5; j++) { printf(”%.3f “, obs_b[n].obs[0][j]); } printf(”…\n”); } } if (epochnum > 3) { printf(”\n… 还有 %d 个历元未显示\n”, epochnum - 3); } } int main() { FILE* fp_obs = NULL; pobs_head obs_h = NULL; pobs_epoch obs_e = NULL; pobs_body obs_b = NULL; printf(“RINEX观测值文件读取程序\n”); printf(“来源:https://blog.youkuaiyun.com/why1472587/article/details/127514022\n\n”); // 打开观测值文件 fp_obs = fopen(“sample.15o”, “r”); if (fp_obs == NULL) { printf(“错误:无法打开文件 sample.15o\n”); printf(“请确保示例文件存在于当前目录中。\n”); return 1; } // 获取历元数 int o_epochnum = get_epochnum(fp_obs); rewind(fp_obs); printf(“检测到 %d 个历元\n”, o_epochnum); // 分配内存 obs_h = (pobs_head)malloc(sizeof(obs_head)); obs_e = (pobs_epoch)malloc(sizeof(obs_epoch) * o_epochnum); obs_b = (pobs_body)malloc(sizeof(obs_body) * o_epochnum); if (!obs_h || !obs_e || !obs_b) { printf(“内存分配失败\n”); fclose(fp_obs); return 1; } // 读取数据 read_h(fp_obs, obs_h); read_b(fp_obs, obs_e, obs_b, obs_h->obstypenum); // 显示结果 display_header(obs_h); display_epoch_data(obs_e, obs_b, o_epochnum, obs_h->obstypenum); // 清理 fclose(fp_obs); free(obs_h); free(obs_e); free(obs_b); printf(“数据读取完成!\n”); return 0; }按如上代码思想参考或其它,读取RINEX3.04版本观测文件,满足如下要求:题目内容:按以下功能要求,读取一个GNSS观测文件: 系统和频率要求为GPS L11575.42 MHz)和L2(1227.60 MHz),GLONASS G11602+k9/16)和G2(1246+k7/16),BDS B1(L2,1561.098 MHz)和B3(L6,1268.52 MHz),Galileo E1(L11575.42 MHz)和E5a(L5,1176.45 MHz); 读取伪距,载波,信噪比和多普勒这四类观测值; 对于GPS L1和L2,分别按跟踪模式"CSLXPWYM"和"CDSLXPWYM"优先级选用观测值;对于GLONASS G1和G2,按跟踪模式"CP"优先级选用观测值;对于BDS B1和B3,按跟踪模式"IQX"优先级选用观测值;对于GAL E1和E5a,分别按跟踪模式"ABCXZ"和"IQX"优先级选用观测值;定义右边优先级高于左边; 读取完整一天所有历元的观测数据。 输入格式:Rinex 3.04标准格式的观测文件 输出格式:按以下要求输出: 依次输出时间,系统,卫星,两个频率的伪距、载波、多普勒、信噪比和跟踪模式; 按时间第一顺序、系统第二顺序、卫星第三顺序,逐行输出整点时刻的所有观测信息; 格式整洁美观,观测值采用小数输出,小数点保留4位,不少于原始数据小数位。能在VS上正确运行,输出完整代码,一定要读完整历元和观测数据.我的读取的文件路径为"D:\qq\jfng1590.24o",输出后结果保存在"D:\qq\output_obs.txt"
10-20
#ifndef _LINUX_MODULE_PARAMS_H #define _LINUX_MODULE_PARAMS_H /* (C) Copyright 2001, 2002 Rusty Russell IBM Corporation */ #include <linux/init.h> #include <linux/stringify.h> #include <linux/kernel.h> /* You can override this manually, but generally this should match the module name. */ #ifdef MODULE #define MODULE_PARAM_PREFIX /* empty */ #else #define MODULE_PARAM_PREFIX KBUILD_MODNAME "." #endif /* Chosen so that structs with an unsigned long line up. */ #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long)) /* This struct is here for syntactic coherency, it is not used */ #define __MODULE_INFO_DISABLED(name) \ struct __UNIQUE_ID(name) {} #ifdef CONFIG_MODULE_STRIPPED #define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name) #else #define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info) #endif #ifdef MODULE #define __MODULE_INFO(tag, name, info) \ static const char __UNIQUE_ID(name)[] \ __used __attribute__((section(".modinfo"), unused, aligned(1))) \ = __stringify(tag) "=" info #else /* !MODULE */ /* This struct is here for syntactic coherency, it is not used */ #define __MODULE_INFO(tag, name, info) __MODULE_INFO_DISABLED(name) #endif #define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type) /* One for each parameter, describing how to use it. Some files do multiple of these per line, so can't just use MODULE_INFO. */ #define MODULE_PARM_DESC(_parm, desc) \ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc) struct kernel_param; /* * Flags available for kernel_param_ops * * NOARG - the parameter allows for no argument (foo instead of foo=1) */ enum { KERNEL_PARAM_OPS_FL_NOARG = (1 << 0) }; struct kernel_param_ops { /* How the ops should behave */ unsigned int flags; /* Returns 0, or -errno. arg is in kp->arg. */ int (*set)(const char *val, const struct kernel_param *kp); /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ int (*get)(char *buffer, const struct kernel_param *kp); /* Optional function to free kp->arg when module unloaded. */ void (*free)(void *arg); }; /* * Flags available for kernel_param * * UNSAFE - the parameter is dangerous and setting it will taint the kernel */ enum { KERNEL_PARAM_FL_UNSAFE = (1 << 0) }; struct kernel_param { const char *name; struct module *mod; const struct kernel_param_ops *ops; const u16 perm; s8 level; u8 flags; union { void *arg; const struct kparam_string *str; const struct kparam_array *arr; }; }; extern const struct kernel_param __start___param[], __stop___param[]; /* Special one for strings we want to copy into */ struct kparam_string { unsigned int maxlen; char *string; }; /* Special one for arrays */ struct kparam_array { unsigned int max; unsigned int elemsize; unsigned int *num; const struct kernel_param_ops *ops; void *elem; }; /** * module_param - typesafe helper for a module/cmdline parameter * @value: the variable to alter, and exposed parameter name. * @type: the type of the parameter * @perm: visibility in sysfs. * * @value becomes the module parameter, or (prefixed by KBUILD_MODNAME and a * ".") the kernel commandline parameter. Note that - is changed to _, so * the user can use "foo-bar=1" even for variable "foo_bar". * * @perm is 0 if the the variable is not to appear in sysfs, or 0444 * for world-readable, 0644 for root-writable, etc. Note that if it * is writable, you may need to use kernel_param_lock() around * accesses (esp. charp, which can be kfreed when it changes). * * The @type is simply pasted to refer to a param_ops_##type and a * param_check_##type: for convenience many standard types are provided but * you can create your own by defining those variables. * * Standard types are: * byte, short, ushort, int, uint, long, ulong * charp: a character pointer * bool: a bool, values 0/1, y/n, Y/N. * invbool: the above, only sense-reversed (N = true). */ #define module_param(name, type, perm) \ module_param_named(name, name, type, perm) /** * module_param_unsafe - same as module_param but taints kernel */ #define module_param_unsafe(name, type, perm) \ module_param_named_unsafe(name, name, type, perm) /** * module_param_named - typesafe helper for a renamed module/cmdline parameter * @name: a valid C identifier which is the parameter name. * @value: the actual lvalue to alter. * @type: the type of the parameter * @perm: visibility in sysfs. * * Usually it's a good idea to have variable names and user-exposed names the * same, but that's harder if the variable must be non-static or is inside a * structure. This allows exposure under a different name. */ #define module_param_named(name, value, type, perm) \ param_check_##type(name, &(value)); \ module_param_cb(name, &param_ops_##type, &value, perm); \ __MODULE_PARM_TYPE(name, #type) /** * module_param_named_unsafe - same as module_param_named but taints kernel */ #define module_param_named_unsafe(name, value, type, perm) \ param_check_##type(name, &(value)); \ module_param_cb_unsafe(name, &param_ops_##type, &value, perm); \ __MODULE_PARM_TYPE(name, #type) /** * module_param_cb - general callback for a module/cmdline parameter * @name: a valid C identifier which is the parameter name. * @ops: the set & get operations for this parameter. * @perm: visibility in sysfs. * * The ops can have NULL set or get functions. */ #define module_param_cb(name, ops, arg, perm) \ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0) #define module_param_cb_unsafe(name, ops, arg, perm) \ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, \ KERNEL_PARAM_FL_UNSAFE) /** * <level>_param_cb - general callback for a module/cmdline parameter * to be evaluated before certain initcall level * @name: a valid C identifier which is the parameter name. * @ops: the set & get operations for this parameter. * @perm: visibility in sysfs. * * The ops can have NULL set or get functions. */ #define __level_param_cb(name, ops, arg, perm, level) \ __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, level, 0) #define core_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 1) #define postcore_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 2) #define arch_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 3) #define subsys_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 4) #define fs_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 5) #define device_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 6) #define late_param_cb(name, ops, arg, perm) \ __level_param_cb(name, ops, arg, perm, 7) /* On alpha, ia64 and ppc64 relocations to global data cannot go into read-only sections (which is part of respective UNIX ABI on these platforms). So 'const' makes no sense and even causes compile failures with some compilers. */ #if defined(CONFIG_ALPHA) || defined(CONFIG_IA64) || defined(CONFIG_PPC64) #define __moduleparam_const #else #define __moduleparam_const const #endif /* This is the fundamental function for registering boot/module parameters. */ #define __module_param_call(prefix, name, ops, arg, perm, level, flags) \ /* Default value instead of permissions? */ \ static const char __param_str_##name[] = prefix #name; \ static struct kernel_param __moduleparam_const __param_##name \ __used \ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ = { __param_str_##name, THIS_MODULE, ops, \ VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } } /* Obsolete - use module_param_cb() */ #define module_param_call(name, set, get, arg, perm) \ static const struct kernel_param_ops __param_ops_##name = \ { .flags = 0, (void *)set, (void *)get }; \ __module_param_call(MODULE_PARAM_PREFIX, \ name, &__param_ops_##name, arg, \ (perm) + sizeof(__check_old_set_param(set))*0, -1, 0) /* We don't get oldget: it's often a new-style param_get_uint, etc. */ static inline int __check_old_set_param(int (*oldset)(const char *, struct kernel_param *)) { return 0; } #ifdef CONFIG_SYSFS extern void kernel_param_lock(struct module *mod); extern void kernel_param_unlock(struct module *mod); #else static inline void kernel_param_lock(struct module *mod) { } static inline void kernel_param_unlock(struct module *mod) { } #endif #ifndef MODULE /** * core_param - define a historical core kernel parameter. * @name: the name of the cmdline and sysfs parameter (often the same as var) * @var: the variable * @type: the type of the parameter * @perm: visibility in sysfs * * core_param is just like module_param(), but cannot be modular and * doesn't add a prefix (such as "printk."). This is for compatibility * with __setup(), and it makes sense as truly core parameters aren't * tied to the particular file they're in. */ #define core_param(name, var, type, perm) \ param_check_##type(name, &(var)); \ __module_param_call("", name, &param_ops_##type, &var, perm, -1, 0) /** * core_param_unsafe - same as core_param but taints kernel */ #define core_param_unsafe(name, var, type, perm) \ param_check_##type(name, &(var)); \ __module_param_call("", name, &param_ops_##type, &var, perm, \ -1, KERNEL_PARAM_FL_UNSAFE) #endif /* !MODULE */ /** * module_param_string - a char array parameter * @name: the name of the parameter * @string: the string variable * @len: the maximum length of the string, incl. terminator * @perm: visibility in sysfs. * * This actually copies the string when it's set (unlike type charp). * @len is usually just sizeof(string). */ #define module_param_string(name, string, len, perm) \ static const struct kparam_string __param_string_##name \ = { len, string }; \ __module_param_call(MODULE_PARAM_PREFIX, name, \ &param_ops_string, \ .str = &__param_string_##name, perm, -1, 0);\ __MODULE_PARM_TYPE(name, "string") /** * parameq - checks if two parameter names match * @name1: parameter name 1 * @name2: parameter name 2 * * Returns true if the two parameter names are equal. * Dashes (-) are considered equal to underscores (_). */ extern bool parameq(const char *name1, const char *name2); /** * parameqn - checks if two parameter names match * @name1: parameter name 1 * @name2: parameter name 2 * @n: the length to compare * * Similar to parameq(), except it compares @n characters. */ extern bool parameqn(const char *name1, const char *name2, size_t n); /* Called on module insert or kernel boot */ extern char *parse_args(const char *name, char *args, const struct kernel_param *params, unsigned num, s16 level_min, s16 level_max, void *arg, int (*unknown)(char *param, char *val, const char *doing, void *arg)); /* Called by module remove. */ #ifdef CONFIG_SYSFS extern void destroy_params(const struct kernel_param *params, unsigned num); #else static inline void destroy_params(const struct kernel_param *params, unsigned num) { } #endif /* !CONFIG_SYSFS */ /* All the helper functions */ /* The macros to do compile-time type checking stolen from Jakub Jelinek, who IIRC came up with this idea for the 2.4 module init code. */ #define __param_check(name, p, type) \ static inline type __always_unused *__check_##name(void) { return(p); } extern const struct kernel_param_ops param_ops_byte; extern int param_set_byte(const char *val, const struct kernel_param *kp); extern int param_get_byte(char *buffer, const struct kernel_param *kp); #define param_check_byte(name, p) __param_check(name, p, unsigned char) extern const struct kernel_param_ops param_ops_short; extern int param_set_short(const char *val, const struct kernel_param *kp); extern int param_get_short(char *buffer, const struct kernel_param *kp); #define param_check_short(name, p) __param_check(name, p, short) extern const struct kernel_param_ops param_ops_ushort; extern int param_set_ushort(const char *val, const struct kernel_param *kp); extern int param_get_ushort(char *buffer, const struct kernel_param *kp); #define param_check_ushort(name, p) __param_check(name, p, unsigned short) extern const struct kernel_param_ops param_ops_int; extern int param_set_int(const char *val, const struct kernel_param *kp); extern int param_get_int(char *buffer, const struct kernel_param *kp); #define param_check_int(name, p) __param_check(name, p, int) extern const struct kernel_param_ops param_ops_uint; extern int param_set_uint(const char *val, const struct kernel_param *kp); extern int param_get_uint(char *buffer, const struct kernel_param *kp); #define param_check_uint(name, p) __param_check(name, p, unsigned int) extern const struct kernel_param_ops param_ops_long; extern int param_set_long(const char *val, const struct kernel_param *kp); extern int param_get_long(char *buffer, const struct kernel_param *kp); #define param_check_long(name, p) __param_check(name, p, long) extern const struct kernel_param_ops param_ops_ulong; extern int param_set_ulong(const char *val, const struct kernel_param *kp); extern int param_get_ulong(char *buffer, const struct kernel_param *kp); #define param_check_ulong(name, p) __param_check(name, p, unsigned long) extern const struct kernel_param_ops param_ops_ullong; extern int param_set_ullong(const char *val, const struct kernel_param *kp); extern int param_get_ullong(char *buffer, const struct kernel_param *kp); #define param_check_ullong(name, p) __param_check(name, p, unsigned long long) extern const struct kernel_param_ops param_ops_charp; extern int param_set_charp(const char *val, const struct kernel_param *kp); extern int param_get_charp(char *buffer, const struct kernel_param *kp); extern void param_free_charp(void *arg); #define param_check_charp(name, p) __param_check(name, p, char *) /* We used to allow int as well as bool. We're taking that away! */ extern const struct kernel_param_ops param_ops_bool; extern int param_set_bool(const char *val, const struct kernel_param *kp); extern int param_get_bool(char *buffer, const struct kernel_param *kp); #define param_check_bool(name, p) __param_check(name, p, bool) extern const struct kernel_param_ops param_ops_bool_enable_only; extern int param_set_bool_enable_only(const char *val, const struct kernel_param *kp); /* getter is the same as for the regular bool */ #define param_check_bool_enable_only param_check_bool extern const struct kernel_param_ops param_ops_invbool; extern int param_set_invbool(const char *val, const struct kernel_param *kp); extern int param_get_invbool(char *buffer, const struct kernel_param *kp); #define param_check_invbool(name, p) __param_check(name, p, bool) /* An int, which can only be set like a bool (though it shows as an int). */ extern const struct kernel_param_ops param_ops_bint; extern int param_set_bint(const char *val, const struct kernel_param *kp); #define param_get_bint param_get_int #define param_check_bint param_check_int /** * module_param_array - a parameter which is an array of some type * @name: the name of the array variable * @type: the type, as per module_param() * @nump: optional pointer filled in with the number written * @perm: visibility in sysfs * * Input and output are as comma-separated values. Commas inside values * don't work properly (eg. an array of charp). * * ARRAY_SIZE(@name) is used to determine the number of elements in the * array, so the definition must be visible. */ #define module_param_array(name, type, nump, perm) \ module_param_array_named(name, name, type, nump, perm) /** * module_param_array_named - renamed parameter which is an array of some type * @name: a valid C identifier which is the parameter name * @array: the name of the array variable * @type: the type, as per module_param() * @nump: optional pointer filled in with the number written * @perm: visibility in sysfs * * This exposes a different name than the actual variable name. See * module_param_named() for why this might be necessary. */ #define module_param_array_named(name, array, type, nump, perm) \ param_check_##type(name, &(array)[0]); \ static const struct kparam_array __param_arr_##name \ = { .max = ARRAY_SIZE(array), .num = nump, \ .ops = &param_ops_##type, \ .elemsize = sizeof(array[0]), .elem = array }; \ __module_param_call(MODULE_PARAM_PREFIX, name, \ &param_array_ops, \ .arr = &__param_arr_##name, \ perm, -1, 0); \ __MODULE_PARM_TYPE(name, "array of " #type) extern const struct kernel_param_ops param_array_ops; extern const struct kernel_param_ops param_ops_string; extern int param_set_copystring(const char *val, const struct kernel_param *); extern int param_get_string(char *buffer, const struct kernel_param *kp); /* for exporting parameters in /sys/module/.../parameters */ struct module; #if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES) extern int module_param_sysfs_setup(struct module *mod, const struct kernel_param *kparam, unsigned int num_params); extern void module_param_sysfs_remove(struct module *mod); #else static inline int module_param_sysfs_setup(struct module *mod, const struct kernel_param *kparam, unsigned int num_params) { return 0; } static inline void module_param_sysfs_remove(struct module *mod) { } #endif #endif /* _LINUX_MODULE_PARAMS_H */ 这段代码中module_param的作用
最新发布
12-20
/* RINEX观测值文件读取程序 来源:https://blog.youkuaiyun.com/why1472587/article/details/127514022 本程序用于读取RINEX 2.1.1格式的观测值文件(O文件) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define MAXRINEX 84 // 最大读取字符数 // 观测值头文件结构体 typedef struct obs_head { double ver; // RINEX文件版本号 char type[30]; // 文件类型 double apX; // 测站近似位置X double apY; // 测站近似位置Y double apZ; // 测站近似位置Z double ANTH; // 天线高 double ANTdeltaE; // 天线中心东向偏移量 double ANTdeltaN; // 天线中心北向偏移量 int WAFL1; // L1载波波长因子 int WAFL2; // L2载波波长因子 int WAFflag; int obstypenum; // 观测值类型数量 char obstype[15]; // 观测值类型列表 double interval; // 观测值历元间隔 int f_y; // 第一个观测记录的年 int f_m; // 第一个观测记录的月 int f_d; // 第一个观测记录的日 int f_h; // 第一个观测记录的时 int f_min; // 第一个观测记录的分 double f_sec; // 第一个观测记录的秒 char tsys[5]; // 时间系统 } obs_head, *pobs_head; // 观测值历元数据结构体 typedef struct obs_epoch { int y, m, d, h, min; double sec; int p_flag; // 历元标志 int sat_num; // 当前历元观测到的卫星数量 int sPRN[24]; // 卫星PRN列表 } obs_epoch, *pobs_epoch; // 观测值数据结构体 typedef struct obs_body { double obs[24][15]; // 观测值 [卫星][观测类型] } obs_body, *pobs_body; // 函数声明 extern int get_epochnum(FILE* fp_obs); extern void read_h(FILE* fp_obs, pobs_head obs_h); extern void read_b(FILE* fp_obs, pobs_epoch obs_e, pobs_body obs_b, int type); extern void display_header(pobs_head obs_h); extern void display_epoch_data(pobs_epoch obs_e, pobs_body obs_b, int epochnum, int obstypenum); // 将字符串转换为浮点数 static double strtonum(const char* buff, int i, int n) { double value = 0.0; char str[256] = { 0 }; char* p = str; if (i < 0 || (int)strlen(buff) < i || (int)sizeof(str) - 1 < n) { return 0.0; } for (buff += i; *buff && --n >= 0; buff++) { *p++ = ((*buff == 'D' || *buff == 'd') ? 'e' : *buff); } *p = '\0'; return sscanf(str, "%lf", &value) == 1 ? value : 0.0; } // 获取O文件历元数 extern int get_epochnum(FILE* fp_obs) { int n = 0; // 记录历元数 int satnum = 0; // 记录每个历元的卫星数 char flag; // 存放卫星标志符号’G’ char buff[MAXRINEX];// 存放读取的字符串 while (fgets(buff, MAXRINEX, fp_obs)) { satnum = (int)strtonum(buff, 30, 2); strncpy(&flag, buff + 32, 1); if (flag == 'G') { n++; } // 当卫星数超过12个时,一行存不下会转到下一行 if (flag == 'G' && satnum > 12) { n--; } } return n; } // 读取O文件数据头 extern void read_h(FILE* fp_obs, pobs_head obs_h) { char buff[MAXRINEX] = { 0 }; char* lable = buff + 60; int i = 0; while (fgets(buff, MAXRINEX, fp_obs)) { if (strstr(lable, "RINEX VERSION / TYPE")) { obs_h->ver = strtonum(buff, 0, 9); strncpy(obs_h->type, buff + 20, 30); continue; } else if (strstr(lable, "APPROX POSITION XYZ")) { obs_h->apX = strtonum(buff, 0, 14); obs_h->apY = strtonum(buff, 0 + 14, 14); obs_h->apZ = strtonum(buff, 0 + 14 + 14, 14); continue; } else if (strstr(lable, "ANTENNA: DELTA H/E/N")) { obs_h->ANTH = strtonum(buff, 0, 14); obs_h->ANTdeltaE = strtonum(buff, 14, 14); obs_h->ANTdeltaN = strtonum(buff, 14 + 14, 14); continue; } else if (strstr(lable, "WAVELENGTH FACT L1/2")) { obs_h->WAFL1 = (int)strtonum(buff, 0, 6); obs_h->WAFL2 = (int)strtonum(buff, 6, 6); obs_h->WAFflag = (int)strtonum(buff, 6 + 6, 6); continue; } else if (strstr(lable, "# / TYPES OF OBSERV")) { obs_h->obstypenum = (int)strtonum(buff, 0, 6); if (obs_h->obstypenum <= 9) { for (i = 0; i < obs_h->obstypenum; i++) { strncpy(&(obs_h->obstype[i]), buff + 10 * i, 2); } } else if (obs_h->obstypenum > 9) { for (i = 0; i < 9; i++) { strncpy(&(obs_h->obstype[i]), buff + 10 * i, 2); } fgets(buff, MAXRINEX, fp_obs); for (i = 0; i < obs_h->obstypenum - 9; i++) { strncpy(&(obs_h->obstype[i + 9]), buff + 10 * i, 2); } } continue; } else if (strstr(lable, "INTERVAL")) { obs_h->interval = strtonum(buff, 0, 11); continue; } else if (strstr(lable, "TIME OF FIRST OBS")) { obs_h->f_y = (int)strtonum(buff, 0, 6); obs_h->f_m = (int)strtonum(buff, 6, 6); obs_h->f_d = (int)strtonum(buff, 6 + 6, 6); obs_h->f_h = (int)strtonum(buff, 6 + 6 + 6, 6); obs_h->f_min = (int)strtonum(buff, 6 + 6 + 6 + 6, 6); obs_h->f_sec = strtonum(buff, 6 + 6 + 6 + 6 + 6, 6); strncpy(obs_h->tsys, buff + 6 + 6 + 6 + 6 + 6 + 18, 3); continue; } else if (strstr(lable, "END OF HEADER")) break; } } // 读取O文件数据块 extern void read_b(FILE* fp_obs, pobs_epoch obs_e, pobs_body obs_b, int type) { int n = 0; // 历元数 int i, j, k; // 循环变量 char buff[MAXRINEX] = { 0 }; char flag = { 0 }; while (fgets(buff, MAXRINEX, fp_obs)) { // 检查是否为历元开始行 if (strlen(buff) < 30) continue; // 读取历元时间 obs_e[n].y = (int)strtonum(buff, 1, 2) + 2000; obs_e[n].m = (int)strtonum(buff, 4, 2); obs_e[n].d = (int)strtonum(buff, 7, 2); obs_e[n].h = (int)strtonum(buff, 10, 2); obs_e[n].min = (int)strtonum(buff, 13, 2); obs_e[n].sec = strtonum(buff, 15, 11); obs_e[n].p_flag = (int)strtonum(buff, 28, 1); obs_e[n].sat_num = (int)strtonum(buff, 29, 3); // 限制卫星数量 if (obs_e[n].sat_num < 0 || obs_e[n].sat_num > 24) { obs_e[n].sat_num = 0; continue; } strncpy(&flag, buff + 32, 1); // 读取卫星PRN if (obs_e[n].sat_num <= 12 && flag == 'G') { for (i = 0; i < obs_e[n].sat_num && i < 24; i++) { obs_e[n].sPRN[i] = (int)strtonum(buff, 33 + 3 * i, 2); } } else if (obs_e[n].sat_num > 12 && flag == 'G') { for (i = 0; i < 12 && i < 24; i++) { obs_e[n].sPRN[i] = (int)strtonum(buff, 33 + 3 * i, 2); } if (fgets(buff, MAXRINEX, fp_obs)) { for (i = 0; i < obs_e[n].sat_num - 12 && i < 12; i++) { obs_e[n].sPRN[i + 12] = (int)strtonum(buff, 33 + 3 * i, 2); } } } // 读取观测数据 for (i = 0; i < obs_e[n].sat_num && i < 24; i++) { int lines = (int)ceil((double)type / 5.0); for (j = 0; j < lines && j < 3; j++) { if (!fgets(buff, MAXRINEX, fp_obs)) break; int values_per_line = (j == lines - 1) ? (type % 5 ? type % 5 : 5) : 5; for (k = 0; k < values_per_line && k < 5; k++) { if (16 * k + 16 <= MAXRINEX) { obs_b[n].obs[i][k + 5 * j] = strtonum(buff, 16 * k, 16); } } } } n++; } } // 显示文件头信息 extern void display_header(pobs_head obs_h) { printf(“=== RINEX文件头信息 =\n"); printf(“版本号: %.2f\n”, obs_h->ver); printf(“文件类型: %.30s\n”, obs_h->type); printf(“测站近似坐标: X=%.3f, Y=%.3f, Z=%.3f\n”, obs_h->apX, obs_h->apY, obs_h->apZ); printf(“天线高: %.3f\n”, obs_h->ANTH); printf(“天线偏移: E=%.3f, N=%.3f\n”, obs_h->ANTdeltaE, obs_h->ANTdeltaN); printf(“观测值类型数量: %d\n”, obs_h->obstypenum); printf(“观测值类型: “); for (int i = 0; i < obs_h->obstypenum; i++) { printf(”%c%c “, obs_h->obstype[i2], obs_h->obstype[i2+1]); } printf(”\n采样间隔: %.1f秒\n”, obs_h->interval); printf(“起始时间: %04d-%02d-%02d %02d:%02d:%.0f\n”, obs_h->f_y, obs_h->f_m, obs_h->f_d, obs_h->f_h, obs_h->f_min, obs_h->f_sec); printf(“时间系统: %.3s\n”, obs_h->tsys); printf("======================\n\n”); } // 显示历元数据 extern void display_epoch_data(pobs_epoch obs_e, pobs_body obs_b, int epochnum, int obstypenum) { printf(“=== 历元数据摘要 ===\n”); printf(“总历元数: %d\n”, epochnum); for (int n = 0; n < epochnum && n < 3; n++) { // 只显示前3个历元 printf("\n历元 %d:\n", n+1); printf("时间: %04d-%02d-%02d %02d:%02d:%.0f\n", obs_e[n].y, obs_e[n].m, obs_e[n].d, obs_e[n].h, obs_e[n].min, obs_e[n].sec); printf("卫星数量: %d\n", obs_e[n].sat_num); printf("卫星列表: "); for (int i = 0; i < obs_e[n].sat_num; i++) { printf("G%02d ", obs_e[n].sPRN[i]); } printf("\n"); // 显示第一个卫星的前几个观测值 if (obs_e[n].sat_num > 0) { printf("G%02d观测值: ", obs_e[n].sPRN[0]); for (int j = 0; j < obstypenum && j < 5; j++) { printf("%.3f ", obs_b[n].obs[0][j]); } printf("...\n"); } } if (epochnum > 3) { printf("\n... 还有 %d 个历元未显示\n", epochnum - 3); } } int main() { FILE* fp_obs = NULL; pobs_head obs_h = NULL; pobs_epoch obs_e = NULL; pobs_body obs_b = NULL; printf("RINEX观测值文件读取程序\n"); printf("来源:https://blog.youkuaiyun.com/why1472587/article/details/127514022\n\n"); // 打开观测值文件 fp_obs = fopen("sample.15o", "r"); if (fp_obs == NULL) { printf("错误:无法打开文件 sample.15o\n"); printf("请确保示例文件存在于当前目录中。\n"); return 1; } // 获取历元数 int o_epochnum = get_epochnum(fp_obs); rewind(fp_obs); printf("检测到 %d 个历元\n", o_epochnum); // 分配内存 obs_h = (pobs_head)malloc(sizeof(obs_head)); obs_e = (pobs_epoch)malloc(sizeof(obs_epoch) * o_epochnum); obs_b = (pobs_body)malloc(sizeof(obs_body) * o_epochnum); if (!obs_h || !obs_e || !obs_b) { printf("内存分配失败\n"); fclose(fp_obs); return 1; } // 读取数据 read_h(fp_obs, obs_h); read_b(fp_obs, obs_e, obs_b, obs_h->obstypenum); // 显示结果 display_header(obs_h); display_epoch_data(obs_e, obs_b, o_epochnum, obs_h->obstypenum); // 清理 fclose(fp_obs); free(obs_h); free(obs_e); free(obs_b); printf("数据读取完成!\n"); return 0; }基于这段代码思想写读取RINEX3.04版本观测文件的代码,要求:系统和频率要求为GPS L11575.42 MHz)和L2(1227.60 MHz),GLONASS G11602+k9/16)和G2(1246+k7/16),BDS B1(L2,1561.098 MHz)和B3(L6,1268.52 MHz),Galileo E1(L11575.42 MHz)和E5a(L5,1176.45 MHz); 读取伪距,载波,信噪比和多普勒这四类观测值; 对于GPS L1和L2,分别按跟踪模式"CSLXPWYM"和"CDSLXPWYM"优先级选用观测值;对于GLONASS G1和G2,按跟踪模式"CP"优先级选用观测值;对于BDS B1和B3,按跟踪模式"IQX"优先级选用观测值;对于GAL E1和E5a,分别按跟踪模式"ABCXZ"和"IQX"优先级选用观测值;定义右边优先级高于左边; 读取完整一天所有历元的观测数据。 输入格式:Rinex 3.04标准格式的观测文件 输出格式:按以下要求输出: 依次输出时间,系统,卫星,两个频率的伪距、载波、多普勒、信噪比和跟踪模式; 按时间第一顺序、系统第二顺序、卫星第三顺序,逐行输出整点时刻的所有观测信息; 格式整洁美观,观测值采用小数输出,小数点保留4位,不少于原始数据小数位。读取路径为"D:\qq\jfng1590.24o",输出结果路径为"D:\qq\output_obs.txt"
10-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值