Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何确定指针是否等于数组的元素?_C_Arrays_Pointers_Language Lawyer - Fatal编程技术网

C 如何确定指针是否等于数组的元素?

C 如何确定指针是否等于数组的元素?,c,arrays,pointers,language-lawyer,C,Arrays,Pointers,Language Lawyer,我有一个“工程”如预期,但可能有 代码有一个大小相同的数组char数组,称为GP2\u格式[]。要检测指针格式是否与其中一个元素GP2_format[][0]的地址具有相同的值,下面的代码简单测试了指针是否是=最小的元素,如果您希望符合C标准,则您的选项是: 执行单个==或=针对目标范围内的每个指针进行测试 如果这是一个非常大的集合,您可以使用哈希表或搜索树或其他方法来加快速度 重新设计代码,使其不需要此检查 “可能有效”的方法是将所有值强制转换为uintptru\t,然后进行关系比较

我有一个“工程”如预期,但可能有


代码有一个大小相同的数组char数组,称为GP2\u格式[]。要检测指针
格式
是否与其中一个元素
GP2_format[][0]
的地址具有相同的值,下面的代码简单测试了指针是否是
=
最小的元素,如果您希望符合C标准,则您的选项是:

  • 执行单个
    ==
    =针对目标范围内的每个指针进行测试
    
    • 如果这是一个非常大的集合,您可以使用哈希表或搜索树或其他方法来加快速度
  • 重新设计代码,使其不需要此检查

“可能有效”的方法是将所有值强制转换为
uintptru\t
,然后进行关系比较。如果系统具有具有绝对顺序的内存模型,则应定义
uintptru\t
并保留该顺序;如果它没有这样的模型,那么关系比较的想法无论如何也不会起作用。

如果你想遵守C标准,那么你的选择是:

  • 执行单个
    ==
    =针对目标范围内的每个指针进行测试
    
    • 如果这是一个非常大的集合,您可以使用哈希表或搜索树或其他方法来加快速度
  • 重新设计代码,使其不需要此检查

“可能有效”的方法是将所有值强制转换为
uintptru\t
,然后进行关系比较。如果系统具有具有绝对顺序的内存模型,则应定义
uintptru\t
并保留该顺序;如果它没有这样一个模型,那么关系比较的想法无论如何也不会起作用。

这不是对所述问题的回答,而是对根本问题的回答

除非我弄错了,否则整个问题都可以通过将
GP_格式
设置为字符串来避免。通过这种方式,问题简化为检查指针是否指向已知字符串,而这不是UB。(如果是,那么使用UB来查找字符并计算其在字符串中的索引将是完全愚蠢的。在我看来,这将是标准中的一个严重缺陷。再说一次,我不是语言律师,只是一个试图编写健壮、可移植C的程序员。幸运的是,标准声明它是为了帮助像m这样的人而编写的e、 而不是编译器编写人员,他们希望在标准技术允许的情况下,通过生成垃圾来避免做繁重的工作。)

下面是我心目中的方法的完整示例。这也适用于clang-3.5,因为我目前使用的机器上最新的GCC是4.8.4版,它不支持
\u Generic()
。如果使用不同版本的clang或gcc,请相应地更改
Makefile
中的第一行,或运行例如
makecc=gcc

首先,
Makefile

CC  := clang-3.5
CFLAGS  := -Wall -Wextra -std=c11 -O2
LD      := $(CC)
LDFLAGS :=
PROGS   := example

.PHONY: all clean

all: clean $(PROGS)

clean:
    rm -f *.o $(PROGS)

%.o: %.c
    $(CC) $(CFLAGS) -c $^

example: out.o main.o
    $(LD) $^ $(LDFLAGS) -o $@
接下来,
out.h

#ifndef   OUT_H
#define   OUT_H 1
#include <stdio.h>

typedef enum {
    out_char,
    out_int,
    out_double,
    out_FILE,
    out_set_fixed,
    out_set_width,
    out_set_decimals,
    out_count
} out_type;

extern const char out_formats[out_count + 1];

extern int outf(FILE *, ...);

#define out(x...) outf(stdout, x)
#define err(x...) outf(stderr, x)

#define OUT(x) _Generic( (x),           \
    FILE *: out_formats + out_FILE,     \
    double: out_formats + out_double,   \
    int:    out_formats + out_int,      \
    char:   out_formats + out_char      ), (x)

#define OUT_END         ((const char *)0)
#define OUT_EOL         "\n", ((const char *)0)
#define OUT_fixed(x)    (out_formats + out_set_fixed), ((int)(x))
#define OUT_width(x)    (out_formats + out_set_width), ((int)(x))
#define OUT_decimals(x) (out_formats + out_set_decimals), ((int)(x))

#endif /* OUT_H */
#ifndef   OUT_H
#define   OUT_H 1
#include <stdio.h>

typedef enum {
    out_string = 1,
    out_int,
    out_double,
    out_set_FILE,
    out_set_fixed,
    out_set_width,
    out_set_decimals,
    out_type_max
} out_type;

extern const char out_formats[out_type_max + 1];

extern int outf(FILE *, ...);

#define out(x...) outf(stdout, x)
#define err(x...) outf(stderr, x)

#define OUT(x) _Generic( (0,x),         \
    FILE *: out_formats + out_set_FILE, \
    double: out_formats + out_double,   \
    int:    out_formats + out_int,      \
    char *: out_formats + out_string    ), (x)

#define OUT_END         ((const char *)0)
#define OUT_EOL         "\n", ((const char *)0)
#define OUT_fixed(x)    (out_formats + out_set_fixed), ((int)(x))
#define OUT_width(x)    (out_formats + out_set_width), ((int)(x))
#define OUT_decimals(x) (out_formats + out_set_decimals), ((int)(x))

#endif /* OUT_H */
请注意,上面缺少偶数
OUT(“字符串文字”)
支持;这是一个非常简单的实现

最后,使用
main.c
来显示使用上述方法的示例:

#include <stdlib.h>
#include "out.h"

int main(void)
{
    double  q = 1.0e6 / 7.0;
    int     x;

    out("Hello, world!\n", OUT_END);

    out("One seventh of a million is ", OUT_decimals(3), OUT(q), " = ", OUT_fixed(1), OUT(q), ".", OUT_EOL);

    for (x = 1; x <= 9; x++)
        out(OUT(stderr), OUT(x), " ", OUT_width(2), OUT(x*x), OUT_EOL);

    return EXIT_SUCCESS;
}
下面是相应修改的实现,
out.c

#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include "out.h"

/* out_formats is a string consisting of ASCII NULs,
 * i.e. an array of zero chars.
 * We only check if a char pointer points to within out_formats,
 * if it points to a zero char; otherwise, it's just a normal
 * string we print as-is.
*/
const char out_formats[out_count + 1] = { 0 };

int outf(FILE *out, ...)
{
    va_list args;

    int     fixed = 0;
    int     width = -1;
    int     decimals = -1;

    if (!out)
        return EINVAL;

    va_start(args, out);

    while (1) {
        const char *const format = va_arg(args, const char *);

        if (!format) {
            va_end(args);
            return 0;
        }

        if (*format) {
            if (fputs(format, out) == EOF) {
                va_end(args);
                return 0;
            }
        } else
        if (format >= out_formats && format < out_formats + sizeof out_formats) {
            switch ((out_type)(format - out_formats)) {

            case out_char:
                if (fprintf(out, "%c", va_arg(args, int)) < 0) {
                    va_end(args);
                    return EIO;
                }
                break;

            case out_int:
                if (fprintf(out, "%*d", width, (int)va_arg(args, int)) < 0) {
                    va_end(args);
                    return EIO;
                }
                break;

            case out_double:
                if (fprintf(out, fixed ? "%*.*f" : "%*.*e", width, decimals, (float)va_arg(args, double)) < 0) {
                    va_end(args);
                    return EIO;
                }
                break;

            case out_FILE:
                out = va_arg(args, FILE *);
                if (!out) {
                    va_end(args);
                    return EINVAL;
                }
                break;

            case out_set_fixed:
                fixed = !!va_arg(args, int);
                break;

            case out_set_width:
                width = va_arg(args, int);
                break;

            case out_set_decimals:
                decimals = va_arg(args, int);
                break;

            case out_count:
                break;
            }
        }
    }
}
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include "out.h"

const char out_formats[out_type_max + 1] = {
    [ out_string ] = out_string,
    [ out_int ] = out_int,
    [ out_double ] = out_double,
    [ out_set_FILE ] = out_set_FILE,
    [ out_set_fixed ] = out_set_fixed,
    [ out_set_width ] = out_set_width,
    [ out_set_decimals ] = out_set_decimals,
};

int outf(FILE *stream, ...)
{
    va_list args;

    /* State (also, stream is included in state) */
    int     fixed = 0;
    int     width = -1;
    int     decimals = -1;

    va_start(args, stream);

    while (1) {
        const char *const format = va_arg(args, const char *);

        if (!format) {
            va_end(args);
            return 0;
        }

        if (*format > 0 && *format < out_type_max && format == out_formats + (size_t)(*format)) {
            switch ((out_type)(*format)) {

            case out_string:
                {
                    const char *s = va_arg(args, char *);
                    if (s && *s) {
                        if (!stream) {
                            va_end(args);
                            return EINVAL;
                        }
                        if (fputs(s, stream) == EOF) {
                            va_end(args);
                            return EINVAL;
                        }
                    }
                }
                break;

            case out_int:
                if (!stream) {
                    va_end(args);
                    return EINVAL;
                }
                if (fprintf(stream, "%*d", width, (int)va_arg(args, int)) < 0) {
                    va_end(args);
                    return EIO;
                }
                break;

            case out_double:
                if (!stream) {
                    va_end(args);
                    return EINVAL;
                }
                if (fprintf(stream, fixed ? "%*.*f" : "%*.*e", width, decimals, va_arg(args, double)) < 0) {
                    va_end(args);
                    return EIO;
                }
                break;

            case out_set_FILE:
                stream = va_arg(args, FILE *);
                if (!stream) {
                    va_end(args);
                    return EINVAL;
                }
                break;

            case out_set_fixed:
                fixed = !!va_arg(args, int);
                break;

            case out_set_width:
                width = va_arg(args, int);
                break;

            case out_set_decimals:
                decimals = va_arg(args, int);
                break;

            case out_type_max:
                /* This is a bug. */
                break;
            }
        } else
        if (*format) {
            if (!stream) {
                va_end(args);
                return EINVAL;
            }
            if (fputs(format, stream) == EOF) {
                va_end(args);
                return EIO;
            }
        }
    }
}
#包括
#包括
#包括
#包括
#包括“out.h”
常量字符输出格式[输出类型最大+1]={
[out\u string]=out\u string,
[out\u int]=out\u int,
[out\u double]=out\u double,
[out\u set\u FILE]=out\u set\u FILE,
[out\u set\u fixed]=out\u set\u fixed,
[out\u set\u width]=out\u set\u width,
[out\u set\u decimals]=out\u set\u decimals,
};
int输出(文件*流,…)
{
va_列表参数;
/*状态(同样,流包含在状态中)*/
int固定=0;
整数宽度=-1;
整数小数=-1;
va_启动(参数、流);
而(1){
常量字符*常量格式=va_arg(args,常量字符*);
如果(!格式){
va_端(args);
返回0;
}
如果(*格式>0&&*格式#include <stdlib.h>
#include "out.h"

int main(void)
{
    double  q = 1.0e6 / 7.0;
    int     x;

    out("Hello, world!\n", OUT_END);

    out("One seventh of a million is ", OUT_decimals(3), OUT(q), " = ", OUT_fixed(1), OUT(q), ".", OUT_EOL);

    for (x = 1; x <= 9; x++)
        out(OUT(stderr), OUT(x), " ", OUT_width(2), OUT(x*x), OUT_EOL);

    return EXIT_SUCCESS;
}
#ifndef   OUT_H
#define   OUT_H 1
#include <stdio.h>

typedef enum {
    out_string = 1,
    out_int,
    out_double,
    out_set_FILE,
    out_set_fixed,
    out_set_width,
    out_set_decimals,
    out_type_max
} out_type;

extern const char out_formats[out_type_max + 1];

extern int outf(FILE *, ...);

#define out(x...) outf(stdout, x)
#define err(x...) outf(stderr, x)

#define OUT(x) _Generic( (0,x),         \
    FILE *: out_formats + out_set_FILE, \
    double: out_formats + out_double,   \
    int:    out_formats + out_int,      \
    char *: out_formats + out_string    ), (x)

#define OUT_END         ((const char *)0)
#define OUT_EOL         "\n", ((const char *)0)
#define OUT_fixed(x)    (out_formats + out_set_fixed), ((int)(x))
#define OUT_width(x)    (out_formats + out_set_width), ((int)(x))
#define OUT_decimals(x) (out_formats + out_set_decimals), ((int)(x))

#endif /* OUT_H */
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include "out.h"

const char out_formats[out_type_max + 1] = {
    [ out_string ] = out_string,
    [ out_int ] = out_int,
    [ out_double ] = out_double,
    [ out_set_FILE ] = out_set_FILE,
    [ out_set_fixed ] = out_set_fixed,
    [ out_set_width ] = out_set_width,
    [ out_set_decimals ] = out_set_decimals,
};

int outf(FILE *stream, ...)
{
    va_list args;

    /* State (also, stream is included in state) */
    int     fixed = 0;
    int     width = -1;
    int     decimals = -1;

    va_start(args, stream);

    while (1) {
        const char *const format = va_arg(args, const char *);

        if (!format) {
            va_end(args);
            return 0;
        }

        if (*format > 0 && *format < out_type_max && format == out_formats + (size_t)(*format)) {
            switch ((out_type)(*format)) {

            case out_string:
                {
                    const char *s = va_arg(args, char *);
                    if (s && *s) {
                        if (!stream) {
                            va_end(args);
                            return EINVAL;
                        }
                        if (fputs(s, stream) == EOF) {
                            va_end(args);
                            return EINVAL;
                        }
                    }
                }
                break;

            case out_int:
                if (!stream) {
                    va_end(args);
                    return EINVAL;
                }
                if (fprintf(stream, "%*d", width, (int)va_arg(args, int)) < 0) {
                    va_end(args);
                    return EIO;
                }
                break;

            case out_double:
                if (!stream) {
                    va_end(args);
                    return EINVAL;
                }
                if (fprintf(stream, fixed ? "%*.*f" : "%*.*e", width, decimals, va_arg(args, double)) < 0) {
                    va_end(args);
                    return EIO;
                }
                break;

            case out_set_FILE:
                stream = va_arg(args, FILE *);
                if (!stream) {
                    va_end(args);
                    return EINVAL;
                }
                break;

            case out_set_fixed:
                fixed = !!va_arg(args, int);
                break;

            case out_set_width:
                width = va_arg(args, int);
                break;

            case out_set_decimals:
                decimals = va_arg(args, int);
                break;

            case out_type_max:
                /* This is a bug. */
                break;
            }
        } else
        if (*format) {
            if (!stream) {
                va_end(args);
                return EINVAL;
            }
            if (fputs(format, stream) == EOF) {
                va_end(args);
                return EIO;
            }
        }
    }
}