I'm currently reading about enums in C. I understand how they work, but can't figure out situations where they could be useful.
Can you give me some simple examples where the usage of enums is appropriate?
They're often used to group related values together:
enum errorcode {
EC_OK = 0,
EC_NOMEMORY,
EC_DISKSPACE,
EC_CONNECTIONBROKE,
EC_KEYBOARD,
EC_PBCK
};
Enums are just a way to declare constant values with more maintainability. The benefits include:
Compilers can automatically assign values when they are opaque.
They mitigate programmers doing bad things like int monday = SUNDAY + 1.
They make it easy to declare all of your related constants in a single spot.
Use them when you have a finite list of distinct, related values, as in the suits of a deck of cards. Avoid them when you have an effectively unbounded list or a list that could often change, as in the set of all car manufacturers.
Sometime you want to express something that is finite and discrete. An example from the GNU C Programming tutorial are compass directions.
enum compass_direction
{
north,
east,
south,
west
};
Another example, where the ability of enums to correspond to integers comes in handy, could be status codes.
Usually you start the OK code with 0, so it can be used in if constructs.
The concept behind an enum is also sometimes called an "enumerated type". That is to say, it's a type all of whose possible values are named and listed as part of the definition of the type.
C actually diverts from that a bit, since if a and b are values in an enum, then a|b is also a valid value of that type, regardless of whether it's listed and named or not. But you don't have to use that fact, you can use an enum just as an enumerated type.
They're appropriate whenever you want a variable whose possible values each represent one of a fixed list of things. They're also sometimes appropriate when you want to define a bunch of related compile-time constants, especially since in C (unlike C++), a const int is not a compile-time constant.
I think that their most useful properties are:
1) You can concisely define a set of distinct constants where you don't really care what the values are as long as they're different. typedef enum { red, green, blue } color; is better than:
#define red 0
#define green 1
#define blue 2
2) A programmer, on seeing a parameter / return value / variable of type color, knows what values are legal and what they mean (or anyway knows how to look that up). Better than making it an int but documenting "this parameter must be one of the color values defined in some header or other".
3) Your debugger, on seeing a variable of type color, may be able to do a reverse lookup, and give red as the value. Better than you looking that up yourself in the source.
4) The compiler, on seeing a switch of an expression of type color, might warn you if there's no default and any of the enumerated values is missing from the list of cases. That helps avoid errors when you're doing something different for each value of the enum.
Enums are primarily used because they are easier to read than integer numbers to programmers. For example, you can create an enum that represents dayy in a week.
enum DAY {Monday, Tuesday....}
Monday is equivalent to integer 0, Tuesday = Monday + 1 etc.
So instead of integers thta represent each week day, you can use a new type DAY to represent this same concept. It is easier to read for the programmer, but it means the same to the compiler.
Related
I am trying to use the Z3 solver (which works over SMT-LIB) to reason over C programs involving structs. I would like some way to represent that the struct is a variable that contains other variables in SMT-LIB, but I can't find a way to do that. Does anyone know of a way to represent C structs in SMT-LIB?
You can use algebraic data types feature of SMTLib 2.6 to model structs. See Section 4.2.3 of http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
This feature allows not only regular struct declarations but also recursive ones; i.e., you can also model structs that have fields of the same type.
I should add that algebraic data types in SMT are actually more general than what you need, they actually can be used to model values constructed with different algebraic constructors. (For the straightforward record case, you'll simply use one constructor.)
Algebraic-data types are rather a new feature in SMTLib, but both Z3 and CVC4 support it. Solver quality might vary depending on the features you use, but if you simply use datatypes to construct and deconstruct values it should work pretty much out of the box.
I am a college student studying programming linguistics. I posted a similar question a while ago, but I mispublished it, and I have a similar question, so I ask for your help.
Questions are as follows.
For an elementary data type in a language with which you are familiar, do the following:
Explain the difference between data objects of that type and the values that those data objects may contain.
In this textbook, data object means the memory location that contains the data value. And Value is one of the attributes of the data object.
What I don't understand is how to compare two concepts, not the same class, with value, one of the attributes of data objects, and data objects, which are its top concepts.
I tried to understand it in various ways, but I couldn't understand it, so I asked for your help. Thank you.
I was solving the problem by setting the language that I am familiar with as C language.
My take on this question is the following:
The data object is a specific physical instance of storage for a value of the type. This physical instance exists in a definite time and the value it contains may change over time. There was a time before it existed and there will be a time when it is gone - maybe temporarily but eventually forever. Two data objects that hold the same value are nevertheless distinct in that they have separate existence.
The value is a nonphysical general principle which is a member of some theoretical set of possible values. The general principal does not exist in time or space but can be thought of as existing in the "Platonic universe of ideal forms"; it is an idea. In a sense, the idea of the value has always existed - before mankind discovered it - and will continue on after mankind is gone. There is no such thing as two distinct values that are the same; if you see two values that are the same, it's actually the same value; there's just one number 2, no matter in what context or how many times you see it used.
In C, the data objects of primitive type int are at-least-16-bit storage buckets for values between (at a minimum range) -2^16 and 2^16-1. Consider this code snippet:
int n1 = 2;
int n2 = 2;
In this code snippet, we have two data objects - n1 and n2 - but just one value - 2.
I may be erring towards pedantry here, but say I have a field in a database that currently has two values (but may contain more in future). I know I could name this as a flag (e.g. MY_FLAG) containing values 0 and 1, but should more values be required (e.g. 0,1,2,3,4), is it still correct to call the field a flag?
I seem to recall reading something previously, that a flag should always be binary, and anything else should be labelled more appropriately, but I may be mistaken. Does anyone know if my thinking is correct? If so, can you point me to any information on this please? My googling has turned nothing up!!
Thanks very much :o)
Flags are usually binary because when we say flag it means either it is up(1) or down(0).
Just like it is used in military to flag up and down in order to show the war-signs. The concept of flagging is taken from there.
Regarding what you are saying
"your words : values be required (e.g. 0,1,2,3,4)"
In such a situation use Enum. Enumerations are build for such cases or sometimes what we do is , we justify the meaning of these numeric values in comments or in separate file so that more memory could be saved(we use tinyInt or bit field). But never name such a situation Flag.
Flags have standard meaning that is either Up or Down. It doesn't mean that you will get error or something but it is not a good practice. Hope you get it.
It's all a matter of conventions and the ability to maintain your database/code effectively. Technically, you can have a column called my_flag defined as a varchar and hold values like "batman" and "barak obama".
By convention, flags are boolean. If you intend to have other values there, it's probably a better idea to call the column something else, like some_enum, or my_code.
Very occasionally, people talk about (for example) tri-state flags, but Wikipedia and most of the dictionary definitions that I read reserve "flag" for binary / two state uses1.
Of course, neither Wikipedia or any dictionary has the authority to say some English usage is "incorrect". "Correct" usage is really "conventional" usage; i.e. what other people say / write.
I would argue that saying or writing "tri-state flag" is unconventional, but it is unambiguous and serves its purpose of communicating a concept adequately. (And the usage can be justified ...)
1 - Most, but not all; see http://www.oxforddictionaries.com/definition/english/flag.
Don't call anything "flag". Or "count" or "mark" or "int" or "code". Name it like everything else in code: after what it means.
workday {mon..fri}
tall {yes,no}
zip_code {00000..99999}
state {AL..WY}
Notice that (something like) yes/no plays the 'flag' role of indicating a permanent dichotomy. (In lieu of boolean, which does that in the rest of the universe outside SQL). For when the specification/contract really is whether something is so. If a design might add more values you should use a different type.
Of course if you want to add more info to a name you can. Add distinctions that are meaningful if you can.
workday {monday..friday}
workday_abbrev {mon..fri}
is_tall {yes,no}
zip_plus_5 {00000-99..99999-99}
state_name {Alabama..Wyoming}
state_2 {AL..WY}
I'm writing a bison/flex parser, with multiple data types, all compatible with ANSI C. It won't be a C language, but will retain its data types.
Thing is... I am not sure how to do this correctly.
For example, in an expression, say 'n1' + 'n2', if 'n1' is double and 'n2' is a 32 bit integer, I will need to do type conversion right? How to do it correctly?
i.e. I will logically need to evaluate which type is bigger (here it's double), then convert the int32 to double and then perform the add operation, which would result in a double of value n1 + n2.
I also want to provide support for type casting.
What's the best way to do it correctly? Is there a way to do it nicely or will I have to put a billion of conversion functions like uint32todouble, int32todouble, int32tolongdouble, int64tolongdouble, etc etc.
Thanks!
EDIT: I have been asked to clarify my question, so I will.
I agree this is not directly related to bison/flex, but I would like people experienced in this context to hint me.
Say I have such an operation in my own 'programming' language (i would say it's more scripting, but anyways) i.e. the one I would parse :
int64 b = 237847823435ll
int64 a = int64(82 + 3746.3746434 * 265.345 + b)
Here, the int64() pseudo-function is a type cast. First, we can see the 82 is an int constant, followed by 3746.3746434 and 265.345, and b is an int64. So when I do the operation at A, I will have to :
Change the type of 82 to double
Change the type of b to double
Do the calculations
Since we have a double and that we want to cast it to an int64, convert the double to an int64, and store the result in variable 'a'
As you see, it's quite lots of type changes... And I wonder how I can for example do them in the most elegant and less work possible. I'm talking about the internal implementation.
I could for example write things like :
int64_t double_to_int64(double k) {
return (int64_t) k; // make specific double to int64 conversion
}
For each of the types, so I'd have functions specific to each conversion, but it would take quite lots of time to achieve it and bsides it's an ugly way of doing things. Since some of the variables and number tokens in my parser/lexer are stored in buffers (for different reasons), I don't see really how I could find a way to convert from a type to another without doing such functions. Not to mention with all the unsigned/signed types, it will double the number of required functions.
Thanks
This has nothing to do with flex or bison. It is a language design question.
I suggest you have a look at the type promotion features of other languages. For example, C and Java promote byte, char, and short to int whenever used in an expression. So that cuts a lot of cackle straight away.
These operations are single instructions on the hardware. You don't need to write any functions at all; just generate the appropriate code. If you're designing an interpretive system, design the p-code accordingly.
This is from RFC 3749 (Transport Layer Security Protocol Compression Methods):
Compression Methods
TLS [2] includes the following compression method structure in
sections 6.1 and 7.4.1.2 and Appendix sections A.4.1 and A.6:
enum { null(0), (255) } CompressionMethod;
I'm not really familiar with C, but I know enough to mark it as resemblant of C enum. What I can't understand though, are the null(0) and (255) parts. I can't seem to find anywhere what parentheses and null would mean in this context.
(I seems hard to even come up with a (Google?) search pattern that would consist of something less ubiquitous than "rfc", "null", "c", "parentheses" and would lead me to other places than questions on "null function pointer" or the most fundamental basics.)
So what do these notations mean syntactically?
Why is 255 in parentheses?
Why null looks like a function call?
Is this even supposed to be C? Or is it a common notation shared across RFCs? And if it's C, is it specific to enum?
How is this different from enum { 0, 255 } CompressionMethod; or enum { NULL, 255 } CompressionMethod;?
You may be overreasoning a bit here :)
You should have quoted the lines that follow your quote:
which allows for later specification of up to 256 different
compression methods.
That already explains what the line means. Now, if you follow the [2] to the list of references, you'll notice it refers to RFC 2246. And that document contains the following paragraph:
4. Presentation language
This document deals with the formatting of data in an external
representation. The following very basic and somewhat casually
defined presentation syntax will be used. The syntax draws from
several sources in its structure. Although it resembles the
programming language "C" in its syntax and XDR [XDR] in both its
syntax and intent, it would be risky to draw too many parallels. The
purpose of this presentation language is to document TLS only, not to
have general application beyond that particular goal.
So, the authors of that RFC seem to have concocted a simple syntax from familiar elements to simplify the representation of the subject of the RFC, namely TLS. For enumerateds, they specify the language used in 4.5:
4.5. Enumerateds
An additional sparse data type is available called enum. A field of
type enum can only assume the values declared in the definition.
Each definition is a different type. Only enumerateds of the same
type may be assigned or compared. Every element of an enumerated must
be assigned a value, as demonstrated in the following example. Since
the elements of the enumerated are not ordered, they can be assigned
any unique value, in any order.
enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;
Enumerateds occupy as much space in the byte stream as would its
maximal defined ordinal value. The following definition would cause
one byte to be used to carry fields of type Color.
enum { red(3), blue(5), white(7) } Color;
One may optionally specify a value without its associated tag to
force the width definition without defining a superfluous element.
In the following example, Taste will consume two bytes in the data
stream but can only assume the values 1, 2 or 4.
enum { sweet(1), sour(2), bitter(4), (32000) } Taste;
The names of the elements of an enumeration are scoped within the
defined type. In the first example, a fully qualified reference to
the second element of the enumeration would be Color.blue. Such
qualification is not required if the target of the assignment is well
specified.
Color color = Color.blue; /* overspecified, legal */
Color color = blue; /* correct, type implicit */
For enumerateds that are never converted to external representation,
the numerical information may be omitted.
enum { low, medium, high } Amount;
What it's saying is CompressionMethod.null has the value 0 and then 255 slots are reserved:
which allows for later specification of up to 256 different
compression methods
(255) informs you the size of this field. So for encoding you know how many bytes you need. If it was (400) you would require 2 bytes to specify the 0 for compressionMethod.nullor 0x00 + 0x00. Because 255 can be represented as 1 byte you only need 0x00.
Essentially it lets you know the size of the enum field.