简体   繁体   English

如何使用C中先前定义的常量定义静态const?

[英]How to define a static const using previously defined constants in C?

This isn't quite answered by static const vs #define or #defining constants in C++ . 在C ++中静态const vs #define#defining常量还不能完全解决这个问题。

In when I did a lot of programming in C, ANSI C was brand new. 当我用C进行大量编程时,ANSI C是全新的。 We mostly used #define to define constants. 我们主要使用#define定义常量。 I've been made aware that this is no longer a best practice ( https://codereview.stackexchange.com/questions/123848/verifying-e-mail-address-in-c/123856#123856 ). 我已经意识到这不再是最佳实践( https://codereview.stackexchange.com/questions/123848/verifying-e-mail-address-in-c/123856#123856 )。

Using #define I can use previous constants to define the current constant, an exampe is 使用#define,我可以使用以前的常量来定义当前常量,例如

#define EMAIL_CHAR_ARRAY_SIZE 40
#define GOOD_EMAIL_ADDRESS  1
#define BAD_EMAIL_ADDRESS 0
#define MIMIMUM_USER_NAME_LENGTH 1
#define AT_SIGN_LENGTH 1
#define DOT_LENGTH 1
#define MINIMUM_DOMAIN_LENGTH 1
#define MINIMUM_ROOT_DOMAIN_LENGTH 2
#define MINIUMUM_EMAIL_LENGTH MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH

I have a program (below) where I have attempted to use static const rather than #define, however the constant MINIUMUM_EMAIL_LENGTH doesn't compile when I try to use static const using the previous constants. 我有一个程序(下面),尝试使用静态const而不是#define,但是当我尝试使用以前的常量使用静态const时,常量MINIUMUM_EMAIL_LENGTH无法编译。 Is there a way to use previously defined constants in a static const TYPE declaration? 有没有办法在静态const TYPE声明中使用先前定义的常量?

const_testemail.c:12:5: error: initializer element is not constant
     static const int MINIUMUM_EMAIL_LENGTH = (MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH);


#include <stdio.h>
#include <string.h>

static const int EMAIL_CHAR_ARRAY_SIZE = 40;
static const int GOOD_EMAIL_ADDRESS  = 1;
static const int BAD_EMAIL_ADDRESS = 0;
static const int MIMIMUM_USER_NAME_LENGTH = 1;
static const int AT_SIGN_LENGTH = 1;
static const int DOT_LENGTH = 1;
static const int MINIMUM_DOMAIN_LENGTH = 1;
static const int MINIMUM_ROOT_DOMAIN_LENGTH = 2;
/*  Doesn't compile 
 *  static const int MINIUMUM_EMAIL_LENGTH = MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH;
 *  */

#define MINIUMUM_EMAIL_LENGTH (MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH)

int isEmailAddressProper(const char EmailAddress[EMAIL_CHAR_ARRAY_SIZE])
{
    int     EmailAddressIsGood = GOOD_EMAIL_ADDRESS;
    int     LengthOfEmailAddress;
    char    *AtSignLocation, *pos2;
    int     rootDomainLength;

    LengthOfEmailAddress = strlen(EmailAddress);
    if (LengthOfEmailAddress < MINIUMUM_EMAIL_LENGTH)
    {
        printf("The length of the email address is less than the minimum lenght %d\n", MINIUMUM_EMAIL_LENGTH);
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    AtSignLocation = strchr(EmailAddress, '@'); /* get the first instance of @ */
    if (!AtSignLocation)
    {
        printf("There is no @ in the email address\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
        return EmailAddressIsGood;
    }

    if (AtSignLocation == EmailAddress) { /* Is @ the first character? */
        printf("There is no user name in the email address, @ is the first character\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    pos2 = strrchr(EmailAddress, '@'); /* find any other @ */
    if ((pos2) && (AtSignLocation != pos2)) {
        printf("There is more than 1 @ in the email address\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    pos2 = strrchr(EmailAddress, '.'); /* get the last instance of '.' */
    if (AtSignLocation > pos2) /* is . before @ ? */
    {            printf("There is no root domain in the email address\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    pos2++;
    rootDomainLength = LengthOfEmailAddress - ((int)(pos2 - EmailAddress));
    /* if root domain less than length 2 */
    if (rootDomainLength < MINIMUM_ROOT_DOMAIN_LENGTH)
    {
        printf("The root domain length (%d) is less than the minimum length required (%d) in the email address\n", rootDomainLength, MINIMUM_ROOT_DOMAIN_LENGTH);
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    return EmailAddressIsGood;
}

void GetAndValidateEmailAddress(char EmailAddress[EMAIL_CHAR_ARRAY_SIZE])
{
    int EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    char TempEmail[EMAIL_CHAR_ARRAY_SIZE];

    while (!EmailAddressIsGood)
    {
        scanf("%39s", TempEmail);
        EmailAddressIsGood = isEmailAddressProper(TempEmail);
        if (!EmailAddressIsGood) {
            printf("The email address is not in the proper format, please re-enter the email address\n");
        }
    }

   strcpy(EmailAddress, TempEmail);
}

main()
{
    char EmailAddress[EMAIL_CHAR_ARRAY_SIZE];

    printf("Please enter the email address\n");
    GetAndValidateEmailAddress(EmailAddress);
    printf("The email address you entered is %s\n", EmailAddress);
}

C does not have symbolic constants other than enum-constants (which are always of type int ). C除了枚举常量 (始终为int类型)以外没有符号常量。 #define is a macro and part of the pre processor. #define是宏,是处理器的一部分。 It is a textual replacement before the actual C language compilation. 它是实际C语言编译之前的文本替换。

const qualified variables are semantically still variables. const限定变量在语义上仍然是变量。 The qualifier is a guarantee by the programmer he will not change the value. 限定符是程序员的保证,他不会更改该值。 The compiler may rely on this guarantee. 编译器可能依赖此保证。 Breaking the contract invokes undefined behaviour, but it is not necessarily enforced by the run-time environment. 违反合同会调用未定义的行为,但不一定由运行时环境强制执行。

Static initialisers and array indexes at the file-level require a constant expression , thus the error. 文件级的静态初始化程序和数组索引需要一个常量表达式 ,因此会产生错误。 Briefly, a constant expression must yield a constant value at compile-time, thus you cannot use variables. 简而言之,一个常量表达式必须在编译时产生一个常量值,因此您不能使用变量。

Note the array parameter in your function has a similar problem. 请注意,函数中的array参数有类似的问题。 But here you can use a variable length array. 但是在这里您可以使用可变长度数组。 However, you either can use an empty length ( [] ) or pass the length as a preceeding parameter explicitly; 但是,您既可以使用空长度( [] ),也可以显式地将长度作为前面的参数传递; global variables don't work: 全局变量不起作用:

int isEmailAddressProper(size_t len, const char EmailAddress[len])

C++ is a different language with similar syntax/grammar, and quite some different semantics even for the same grammar. C ++是另一种语言,具有相似的语法/语法,甚至对于相同的语法也有许多不同的语义。 You often cannot apply knowledge from on language to the other. 您通常无法将语言知识应用于其他语言。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM