473,395 Members | 1,454 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

sizeof pointers

All,

I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would the
internal representation be the same in both cases?

background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.

thanks,
James

Feb 3 '07 #1
38 2554
James Brown wrote:
All,

I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would the
internal representation be the same in both cases?
They could be the same, but this is not guaranteed. Even for systems
where the size and representation are the same, compilers'
optimisations may cause your code to not function the way you want.
background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
If you could be more specific about what you're trying to do,
preferably using a short code snippet, someone may be able to suggest
a way to avoid the issue.

Feb 3 '07 #2
"James Brown" <em***@viahomepage.comwrites:
I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would the
internal representation be the same in both cases?
The standard guarantees, for historical reasons, that void*, char*,
signed char*, and unsigned char* have the same representation and
alignment. It also guarantees, if I recall correctly, that all
pointers to structs and unions have the same representation. Beyond
that, all bets are off.
background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
Any value of any pointer-to-object type can be converted to void* and
back again, yielding the same value. You can probably make use of
that.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 3 '07 #3

"James Brown" <em***@viahomepage.comwrote in
>
I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same
type? Would sizeof(char **) be the same as sizeof(char *)? And if it is,
would the internal representation be the same in both cases?

background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
A char ** is not very similar to to a char *.

A char * points to a list of characters, a char ** to a list of pointers. If
the hardware has 64 bit bytes, and 8 bit chars are supported by bit
twiddling, then char *s will need extra bits to represent the offset. ints
will, naturally, be 64 bits on such a system, so an int * is a raw address.

However a char ** is probably just a pointer to an internal structure - the
character pointers. It would be surprising, though not forbidden, for it to
be different to an int **.

Feb 3 '07 #4
Keith Thompson wrote:
>
The standard guarantees, for historical reasons, that void*, char*,
signed char*, and unsigned char* have the same representation and
alignment. It also guarantees, if I recall correctly, that all
pointers to structs and unions have the same representation. Beyond
that, all bets are off.
Small clarification: All pointers to all kinds of structs
have the same representation; we'll call it representation S.
Also, all pointers to all kinds of unions have the same
representation; we'll call it representation U. It is possible,
in theory at least, that S and U could be different.

--
Eric Sosman
es*****@acm-dot-org.invalid
Feb 3 '07 #5
Eric Sosman <es*****@acm-dot-org.invalidwrites:
Keith Thompson wrote:
The standard guarantees, for historical reasons, that void*, char*,
signed char*, and unsigned char* have the same representation and
alignment. It also guarantees, if I recall correctly, that all
pointers to structs and unions have the same representation. Beyond
that, all bets are off.

Small clarification: All pointers to all kinds of structs
have the same representation; we'll call it representation S.
Also, all pointers to all kinds of unions have the same
representation; we'll call it representation U. It is possible,
in theory at least, that S and U could be different.
Quite correct, thank you.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 3 '07 #6
James Brown wrote:
>
I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same
as sizeof(int *) ? But how about multiple levels of pointers to
the same type? Would sizeof(char **) be the same as sizeof(char *)?
And if it is, would the internal representation be the same in both
cases?
No. What you are guaranteed is that any pointer can be converted
to a void* and back again TO THE ORIGINAL TYPE. You are also
guaranteed that char* and void* have the same representation.
char** is none of these. Neither is int*. Your shortcuts may work
on many machines, but are not guaranteed, and not portable.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Feb 4 '07 #7
On Feb 3, 6:46 pm, "James Brown" <e...@viahomepage.comwrote:
I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would the
internal representation be the same in both cases?
The usual reason why char* would have different size and
representation than say int* is that usually there are many more char
objects addressable than int objects. Say you had an architecture that
supports accessing 2^32 thirty-two bit quantities, and the compiler
decided that int = 32 bit, then int* would have to support 2^32
different values and fit into 32 bit, but char* would have to support
4 * 2^32 = 2^34 different values and could not fit into 32 bit; it
would likely be made 64 bit.

In such an implementation, a pointer to int* would have to support
2^32 different values. A pointer to char* would have to support 2^31
different values, same as a pointer to long long, so it would easily
fit into 32 bit. So if sizeof (char *) != sizeof (int *), then it is
much more likely that sizeof (char **) == sizeof (int *), and not
sizeof (char **) == sizeof (char *).

Feb 4 '07 #8

"Malcolm McLean" <re*******@btinternet.comwrote in message
news:2t******************************@bt.com...
>
"James Brown" <em***@viahomepage.comwrote in
>>
I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same
type? Would sizeof(char **) be the same as sizeof(char *)? And if it is,
would the internal representation be the same in both cases?

background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
A char ** is not very similar to to a char *.

A char * points to a list of characters, a char ** to a list of pointers.
If the hardware has 64 bit bytes, and 8 bit chars are supported by bit
twiddling, then char *s will need extra bits to represent the offset. ints
will, naturally, be 64 bits on such a system, so an int * is a raw
address.

However a char ** is probably just a pointer to an internal structure -
the character pointers. It would be surprising, though not forbidden, for
it to be different to an int **.
understood, thankyou for the clarification.

James

Feb 4 '07 #9
christian.bau escreveu:
On Feb 3, 6:46 pm, "James Brown" <e...@viahomepage.comwrote:
>I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would the
internal representation be the same in both cases?

The usual reason why char* would have different size and
representation than say int* is that usually there are many more char
objects addressable than int objects. Say you had an architecture that
supports accessing 2^32 thirty-two bit quantities, and the compiler
decided that int = 32 bit, then int* would have to support 2^32
different values and fit into 32 bit, but char* would have to support
4 * 2^32 = 2^34 different values and could not fit into 32 bit; it
would likely be made 64 bit.
I think this is an /unsual/ reason. Pointers are intended to store
memory addresses. If one such reasoning of yours were taken to an
implementation, how would you return the pointer difference (for the
sake or argument lets make the two positions contiguous, and stick to a
32 bit architecture):

a) of two pointers to char
b) of two pointers to int
In such an implementation, a pointer to int* would have to support
2^32 different values. A pointer to char* would have to support 2^31
different values, same as a pointer to long long, so it would easily
fit into 32 bit. So if sizeof (char *) != sizeof (int *), then it is
much more likely that sizeof (char **) == sizeof (int *), and not
sizeof (char **) == sizeof (char *).
Do you know of an _existing_ architecture plus C compiler implementation?
Feb 4 '07 #10
"Harald van Dijk" <tr*****@gmail.comwrote in message
news:11**********************@v45g2000cwv.googlegr oups.com...
James Brown wrote:
>All,

I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same
type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would
the
internal representation be the same in both cases?

They could be the same, but this is not guaranteed. Even for systems
where the size and representation are the same, compilers'
optimisations may cause your code to not function the way you want.
>background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.

If you could be more specific about what you're trying to do,
preferably using a short code snippet, someone may be able to suggest
a way to avoid the issue.
Thankyou for your interest. Your comment about 'optimization' is appreciated
also. I will try to explain what I am attempting, but I have no actual
'code' yet - I am still in the 'is this possible' stage, hence my original
question.

I guess what I am trying to do is 'flatten' arbitrary types and maintain
their type information 'out of band'. For example:

1. A (char *) pointer (to an array of characters) would be represented
as-is.
2. An array of pointers-to-char ( char *argv[] for example) would have each
string in the array 'flattened' in turn.
3. A three-level pointer (char ***) would be treated similarly.

My current intention is to write a function that takes a generic pointer
type (void* I guess), along with an array of type-information that describes
each level of indirection in terms of it's size and length. This generic
function would then flatten the specified array/pointer/type/whatever
according to the type information. There might be one function per 'base
type' - i.e. one that handled chars,char*,char**, one that handled int,int*
etc.

For example (note this is not a complete/compilable fragment).

enum TYPE { NONE, ARRAY, POINTER };
struct TYPEINFO
{
enum TYPE type;
int elements;
};

void marshall(struct TYPEINFO *ti, void *ptr);

int main(int argc, char *argv[])
{

/* describe the argv[] array for marshalling purposes */
struct TYPEINFO ti[] = { { ARRAY, argc }, { POINTER, -1 }, { NONE } };

marshall(ti, argv);
return 0;
}

So I 'just' need to implement the marshall function. I would also have a
corresponding 'unmarshall' function that would take the same
type-information and reconstruct the original information (using potentially
different pointer values of course):

char **argv = unmarshall(ti);

I am coming to believe that it will not be possible, at least in a
language-safe manner.

James

Feb 4 '07 #11

"christian.bau" <ch***********@cbau.wanadoo.co.ukwrote in message
news:11**********************@k78g2000cwa.googlegr oups.com...
On Feb 3, 6:46 pm, "James Brown" <e...@viahomepage.comwrote:
>I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same
type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would
the
internal representation be the same in both cases?

The usual reason why char* would have different size and
representation than say int* is that usually there are many more char
objects addressable than int objects. Say you had an architecture that
supports accessing 2^32 thirty-two bit quantities, and the compiler
decided that int = 32 bit, then int* would have to support 2^32
different values and fit into 32 bit, but char* would have to support
4 * 2^32 = 2^34 different values and could not fit into 32 bit; it
would likely be made 64 bit.

In such an implementation, a pointer to int* would have to support
2^32 different values. A pointer to char* would have to support 2^31
different values, same as a pointer to long long, so it would easily
fit into 32 bit. So if sizeof (char *) != sizeof (int *), then it is
much more likely that sizeof (char **) == sizeof (int *), and not
sizeof (char **) == sizeof (char *).
thankyou - that is a nice example that has helped to me understand. I think
my biggest problem is that most of my experience is on 32bit platforms. But
anyway, thanks for your time.

James

Feb 4 '07 #12
"CBFalconer" <cb********@yahoo.comwrote in message
news:45***************@yahoo.com...
James Brown wrote:
>>
I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same
as sizeof(int *) ? But how about multiple levels of pointers to
the same type? Would sizeof(char **) be the same as sizeof(char *)?
And if it is, would the internal representation be the same in both
cases?

No. What you are guaranteed is that any pointer can be converted
to a void* and back again TO THE ORIGINAL TYPE. You are also
guaranteed that char* and void* have the same representation.
char** is none of these. Neither is int*. Your shortcuts may work
on many machines, but are not guaranteed, and not portable.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

This alone (void * conversion) is valuable - thankyou.

Feb 4 '07 #13
Cesar Rabak wrote:
>
.... snip ...
>
I think this is an /unsual/ reason. Pointers are intended to store
memory addresses. If one such reasoning of yours were taken to an
implementation, how would you return the pointer difference (for
the sake or argument lets make the two positions contiguous, and
stick to a 32 bit architecture):
This is elementary. There is no such thing as a pointer difference
unless both pointers point within the same object. There is no
limit on the size of a pointer. In particular, it need not fit
into any size of integer. The only relational operaters available
for all arbitrary pointers are == and !=.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Feb 4 '07 #14
On Feb 4, 4:20 pm, Cesar Rabak <csra...@yahoo.com.brwrote:
Do you know of an _existing_ architecture plus C compiler implementation?
I don't, but then I wouldn't want to predict what architectures will
look like twenty years from now.

Feb 4 '07 #15
James Brown wrote:
"Harald van Dijk" <tr*****@gmail.comwrote in message
news:11**********************@v45g2000cwv.googlegr oups.com...
James Brown wrote:
All,

I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the same
type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is, would
the
internal representation be the same in both cases?
They could be the same, but this is not guaranteed. Even for systems
where the size and representation are the same, compilers'
optimisations may cause your code to not function the way you want.
background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
If you could be more specific about what you're trying to do,
preferably using a short code snippet, someone may be able to suggest
a way to avoid the issue.

Thankyou for your interest. Your comment about 'optimization' is appreciated
also. I will try to explain what I am attempting, but I have no actual
'code' yet - I am still in the 'is this possible' stage, hence my original
question.

I guess what I am trying to do is 'flatten' arbitrary types and maintain
their type information 'out of band'. For example:

1. A (char *) pointer (to an array of characters) would be represented
as-is.
2. An array of pointers-to-char ( char *argv[] for example) would have each
string in the array 'flattened' in turn.
3. A three-level pointer (char ***) would be treated similarly.

My current intention is to write a function that takes a generic pointer
type (void* I guess), along with an array of type-information that describes
each level of indirection in terms of it's size and length. This generic
function would then flatten the specified array/pointer/type/whatever
according to the type information. There might be one function per 'base
type' - i.e. one that handled chars,char*,char**, one that handled int,int*
etc.
Okay, in that case, sorry, it may be possible if you can assume some
system specifics, but in standard C, as you say you suspect, it's not
possible. At least, not for arbitrary depth. Since compilers are
allowed to give char *, char **, char ***, char ****, char *****, etc.
all different representations, portable C code cannot be written that
handles all of them. What you can do is write one version for char *,
one for char **, one for char ***, etc. but it would become a
maintenance nightmare, and it's always possible that you would run
into the need for one more level of indirection too late.

<OTIf you are not limited to C, other languages (including C++)
support type-generic user functions, which may make what you're
looking for possible. </OT>

Feb 4 '07 #16
Cesar Rabak <cs*****@yahoo.com.brwrites:
christian.bau escreveu:
On Feb 3, 6:46 pm, "James Brown" <e...@viahomepage.comwrote:
I believe that the sizeof(char *) may not necessarily be the same
as sizeof(int *) ? But how about multiple levels of pointers to
the same type? Would sizeof(char **) be the same as sizeof(char
*)? And if it is, would the internal representation be the same
in both cases?
The usual reason why char* would have different size and
representation than say int* is that usually there are many more char
objects addressable than int objects. Say you had an architecture that
supports accessing 2^32 thirty-two bit quantities, and the compiler
decided that int = 32 bit, then int* would have to support 2^32
different values and fit into 32 bit, but char* would have to support
4 * 2^32 = 2^34 different values and could not fit into 32 bit; it
would likely be made 64 bit.

I think this is an /unsual/ reason. Pointers are intended to store
memory addresses.
Pointers are intended to point to objects (or to functions, but I
think we're talking about object pointers), and to follow the
semantics defined in the C standard. On many systems, this is most
easily done by using simple memory addresses. On others, it isn't.
If one such reasoning of yours were taken to an
implementation, how would you return the pointer difference (for the
sake or argument lets make the two positions contiguous, and stick to
a 32 bit architecture):

a) of two pointers to char
b) of two pointers to int
Pointer difference (which is defined only for pointers into, or just
past the end of, the same object) is implemented however it needs to
be implemented to yield the correct results.
In such an implementation, a pointer to int* would have to support
2^32 different values. A pointer to char* would have to support 2^31
different values, same as a pointer to long long, so it would easily
fit into 32 bit. So if sizeof (char *) != sizeof (int *), then it is
much more likely that sizeof (char **) == sizeof (int *), and not
sizeof (char **) == sizeof (char *).

Do you know of an _existing_ architecture plus C compiler implementation?
The IBM AS/400 is often mentioned as an example of an architecture
that has a conforming C implementation while violating a lot of the
usual assumptions about how pointers work. I don't know the details
off the top of my head.

Another example is the various models of Cray vector machines. A
memory address can only address 64-bit words, but the C compiler has
CHAR_BIT==8 (the OS is Unix). An int* pointer is just a 64-bit memory
address. A char* or void* pointer is a memory address with an
additional 3-bit offset stored in the otherwise unused high-order 3
bits of the word. The compiler has to emit additional code to
implement arithmetic on char* pointers. All pointers are the same
size, but only because there happen to be unused bits available; it's
easy to imagine a similar system that would need to make char* bigger
than int*.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 4 '07 #17
"James Brown" <em***@viahomepage.comwrites:
[...]
I guess what I am trying to do is 'flatten' arbitrary types and
maintain their type information 'out of band'. For example:

1. A (char *) pointer (to an array of characters) would be represented
as-is.
2. An array of pointers-to-char ( char *argv[] for example) would have
each string in the array 'flattened' in turn.
3. A three-level pointer (char ***) would be treated similarly.
A char** pointer is a pointer to a pointer to char. That's not enough
information to determine what kind of data it points to. In the case
of the argv parameter to main(), it happens to point to the first
element of an array of char*, each of which either is a null pointer
or points to the first element of a null-terminated string. But
that's only one possibility. If you want to flatten the data
structure, you need to know what the data structure is, and that
information may not be available from the C source code (at least not
without a lot of extra analysis of what the code does, which I suspect
would be beyond the scope of your project).

One approach might be to manually annotate the C declarations with
information about how they're used.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 4 '07 #18
Keith Thompson escreveu:
Cesar Rabak <cs*****@yahoo.com.brwrites:
[snipped]
>Do you know of an _existing_ architecture plus C compiler implementation?

The IBM AS/400 is often mentioned as an example of an architecture
that has a conforming C implementation while violating a lot of the
usual assumptions about how pointers work. I don't know the details
off the top of my head.
OK
>
Another example is the various models of Cray vector machines. A
memory address can only address 64-bit words, but the C compiler has
CHAR_BIT==8 (the OS is Unix). An int* pointer is just a 64-bit memory
address. A char* or void* pointer is a memory address with an
additional 3-bit offset stored in the otherwise unused high-order 3
bits of the word. The compiler has to emit additional code to
implement arithmetic on char* pointers. All pointers are the same
size, but only because there happen to be unused bits available; it's
easy to imagine a similar system that would need to make char* bigger
than int*.
I cannot grok this: memory addresses are 64 bit words. What are the
"unused bits available"?
Feb 4 '07 #19
Cesar Rabak <cs*****@yahoo.com.brwrites:
Keith Thompson escreveu:
[...]
Another example is the various models of Cray vector machines. A
memory address can only address 64-bit words, but the C compiler has
CHAR_BIT==8 (the OS is Unix). An int* pointer is just a 64-bit memory
address. A char* or void* pointer is a memory address with an
additional 3-bit offset stored in the otherwise unused high-order 3
bits of the word. The compiler has to emit additional code to
implement arithmetic on char* pointers. All pointers are the same
size, but only because there happen to be unused bits available; it's
easy to imagine a similar system that would need to make char* bigger
than int*.

I cannot grok this: memory addresses are 64 bit words. What are the
"unused bits available"?
A memory address is 64 bits, but no system actually has 16 exawords
(2**64 words) of memory, and the hardware probably wouldn't be capable
of addressing it even if it existed. The high-order bits of an
address are always going to be zero, and thus are available for other
purposes.

I don't know what would happen if you set the high-order bits to
non-zero and then attempted to use it as a word pointer, but any
attempt to do so would invoke undefined behavior anyway.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 4 '07 #20
"James Brown" <em***@viahomepage.comwrites:
"Harald van Dijk" <tr*****@gmail.comwrote in message
news:11**********************@v45g2000cwv.googlegr oups.com...
>James Brown wrote:
>>All,

I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the
same type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is,
would the
internal representation be the same in both cases?

They could be the same, but this is not guaranteed. Even for systems
where the size and representation are the same, compilers'
optimisations may cause your code to not function the way you want.
>>background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.

If you could be more specific about what you're trying to do,
preferably using a short code snippet, someone may be able to suggest
a way to avoid the issue.

Thankyou for your interest. Your comment about 'optimization' is
appreciated also. I will try to explain what I am attempting, but I
have no actual 'code' yet - I am still in the 'is this possible'
stage, hence my original question.

I guess what I am trying to do is 'flatten' arbitrary types and
maintain their type information 'out of band'. For example:

1. A (char *) pointer (to an array of characters) would be represented
as-is.
2. An array of pointers-to-char ( char *argv[] for example) would have
each string in the array 'flattened' in turn.
3. A three-level pointer (char ***) would be treated similarly.

My current intention is to write a function that takes a generic
pointer type (void* I guess), along with an array of type-information
that describes each level of indirection in terms of it's size and
length. This generic function would then flatten the specified
array/pointer/type/whatever according to the type information. There
might be one function per 'base type' - i.e. one that handled
chars,char*,char**, one that handled int,int* etc.

For example (note this is not a complete/compilable fragment).

enum TYPE { NONE, ARRAY, POINTER };
struct TYPEINFO
{
enum TYPE type;
int elements;
};

void marshall(struct TYPEINFO *ti, void *ptr);

int main(int argc, char *argv[])
{

/* describe the argv[] array for marshalling purposes */
struct TYPEINFO ti[] = { { ARRAY, argc }, { POINTER, -1 }, { NONE } };

marshall(ti, argv);
return 0;
}
If this needs to portable you will have trouble as has been discussed
elsethread -- but you have a way out. You have an IDL (is the design
under your control?) and you generate C, so you can generate short
stubs that do the work for specific pointer types.

To marshal[1] a char *** that your IDL tells you is an array you can
generate:

void marshal_char_ppp(char ***p, size_t n)
{
while (n--) marshal_char_pp(*p++);
}

and so on.

I did something much like this for a portable RPC mechanism in the
days before ANSI C (not that the '89 standard would have helped all
that much in this case).

--
Ben.
Feb 5 '07 #21
"Ben Bacarisse" <be********@bsb.me.ukwrote in message
news:87************@bsb.me.uk...
"James Brown" <em***@viahomepage.comwrites:
>"Harald van Dijk" <tr*****@gmail.comwrote in message
news:11**********************@v45g2000cwv.googleg roups.com...
>>James Brown wrote:
All,

I have a quick question regarding the size of pointer-types:

I believe that the sizeof(char *) may not necessarily be the same as
sizeof(int *) ? But how about multiple levels of pointers to the
same type?
Would sizeof(char **) be the same as sizeof(char *)? And if it is,
would the
internal representation be the same in both cases?

They could be the same, but this is not guaranteed. Even for systems
where the size and representation are the same, compilers'
optimisations may cause your code to not function the way you want.

background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe'
across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.

If you could be more specific about what you're trying to do,
preferably using a short code snippet, someone may be able to suggest
a way to avoid the issue.

Thankyou for your interest. Your comment about 'optimization' is
appreciated also. I will try to explain what I am attempting, but I
have no actual 'code' yet - I am still in the 'is this possible'
stage, hence my original question.

I guess what I am trying to do is 'flatten' arbitrary types and
maintain their type information 'out of band'. For example:

1. A (char *) pointer (to an array of characters) would be represented
as-is.
2. An array of pointers-to-char ( char *argv[] for example) would have
each string in the array 'flattened' in turn.
3. A three-level pointer (char ***) would be treated similarly.

My current intention is to write a function that takes a generic
pointer type (void* I guess), along with an array of type-information
that describes each level of indirection in terms of it's size and
length. This generic function would then flatten the specified
array/pointer/type/whatever according to the type information. There
might be one function per 'base type' - i.e. one that handled
chars,char*,char**, one that handled int,int* etc.

For example (note this is not a complete/compilable fragment).

enum TYPE { NONE, ARRAY, POINTER };
struct TYPEINFO
{
enum TYPE type;
int elements;
};

void marshall(struct TYPEINFO *ti, void *ptr);

int main(int argc, char *argv[])
{

/* describe the argv[] array for marshalling purposes */
struct TYPEINFO ti[] = { { ARRAY, argc }, { POINTER, -1 }, {
NONE } };

marshall(ti, argv);
return 0;
}

If this needs to portable you will have trouble as has been discussed
elsethread -- but you have a way out. You have an IDL (is the design
under your control?) and you generate C, so you can generate short
stubs that do the work for specific pointer types.

To marshal[1] a char *** that your IDL tells you is an array you can
generate:

void marshal_char_ppp(char ***p, size_t n)
{
while (n--) marshal_char_pp(*p++);
}

and so on.

I did something much like this for a portable RPC mechanism in the
days before ANSI C (not that the '89 standard would have helped all
that much in this case).

--
Ben.
Yes the IDL is under my control - so I like your suggestion of the 'stubs'

thanks,
James

Feb 5 '07 #22
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"James Brown" <em***@viahomepage.comwrites:
[...]
>I guess what I am trying to do is 'flatten' arbitrary types and
maintain their type information 'out of band'. For example:

1. A (char *) pointer (to an array of characters) would be represented
as-is.
2. An array of pointers-to-char ( char *argv[] for example) would have
each string in the array 'flattened' in turn.
3. A three-level pointer (char ***) would be treated similarly.

A char** pointer is a pointer to a pointer to char. That's not enough
information to determine what kind of data it points to. In the case
of the argv parameter to main(), it happens to point to the first
element of an array of char*, each of which either is a null pointer
or points to the first element of a null-terminated string. But
that's only one possibility. If you want to flatten the data
structure, you need to know what the data structure is, and that
information may not be available from the C source code (at least not
without a lot of extra analysis of what the code does, which I suspect
would be beyond the scope of your project).

One approach might be to manually annotate the C declarations with
information about how they're used.
I guess I should have mentioned - but yes, the 'C' declarations are all
annotated such that I will always know if things are NULL/single
element/variable length etc.
Feb 5 '07 #23
In article <ln************@nuthaus.mib.orgKeith Thompson <ks***@mib.orgwrites:
Cesar Rabak <cs*****@yahoo.com.brwrites:
....
I cannot grok this: memory addresses are 64 bit words. What are the
"unused bits available"?

A memory address is 64 bits, but no system actually has 16 exawords
(2**64 words) of memory, and the hardware probably wouldn't be capable
of addressing it even if it existed. The high-order bits of an
address are always going to be zero, and thus are available for other
purposes.

I don't know what would happen if you set the high-order bits to
non-zero and then attempted to use it as a word pointer, but any
attempt to do so would invoke undefined behavior anyway.
Within the hardware there is no problem. It uses only 24 or 32
low-order bits (depending on the model).
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Feb 5 '07 #24
In article <JC********@cwi.nl>, Dik T. Winter <Di********@cwi.nlwrote:
I don't know what would happen if you set the high-order bits to
non-zero and then attempted to use it as a word pointer, but any
attempt to do so would invoke undefined behavior anyway.
>Within the hardware there is no problem. It uses only 24 or 32
low-order bits (depending on the model).
This has been true on other architectures, and come back to bite those
who relied on it. Unlikely in this case, admittedly.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Feb 5 '07 #25
ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
In article <JC********@cwi.nl>, Dik T. Winter <Di********@cwi.nlwrote:
I don't know what would happen if you set the high-order bits to
non-zero and then attempted to use it as a word pointer, but any
attempt to do so would invoke undefined behavior anyway.
Within the hardware there is no problem. It uses only 24 or 32
low-order bits (depending on the model).

This has been true on other architectures, and come back to bite those
who relied on it. Unlikely in this case, admittedly.
In this case, it's the compiler that depends on it, and the compiler
and hardware are provided by the same vendor.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 5 '07 #26
CBFalconer wrote:
No. What you are guaranteed is that any pointer can be converted
to a void* and back again TO THE ORIGINAL TYPE. You are also
guaranteed that char* and void* have the same representation.
char** is none of these. Neither is int*. Your shortcuts may work
on many machines, but are not guaranteed, and not portable.
This actually brings up a question of mine. I have simple stack code that
consists of the following:

/* code */

typedef struct list_s__ list_s;
struct list_s__ {
list_s *n;
const void *d;
};

extern list_s *ls_push(list_s *lp, const void *d)
{
list_s *lpn;

lpn = ec_malloc(sizeof *lpn);
lpn->n = lp;
lpn->d = d;

return lpn;
}

extern list_s *ls_pop(list_s *lp, void **d)
{
list_s *lpn;

if (lp == NULL) {
if (d) *d = NULL;
return NULL;
}

if (d) *d = (void *)lp->d;
lpn = lp->n;
free(lp);

return lpn;
}

Now the following will always issue a strict aliasing violation w/ gcc if I
cast to void **, rather than void *.

void a(void)
{
list_s *l = NULL;
int *ip, i = 47;

l = ls_push(l, &i);
#ifdef VVP
/* strict aliasing violation, but still "works" */
l = ls_pop(l, (void **)&ip);
#else
/* works, but doesn't feel correct to me */
l = ls_pop(l, (void *)&ip);
#endif
return;
}

$ cc -DVVP -Os -W -Wall -pedantic -g3 -c li.c
li.c: In function 'a':
li.c:11: warning: dereferencing type-punned pointer will break strict-aliasing
rules
$ cc -Os -W -Wall -pedantic -g3 -c li.c
$

Alternatively, I could just change the code to return the data, on pop, rather
than return the head - but it's an idiom I typically use often (checking head
for NULL in a loop construct, basic list stuff, etc). From past google
searches, people have mentioned that casting to void * "fixes" this
diagnostic. My question is "why?" as it expects an argument of void **, and
casting to void * does seem like monkeying around. I do realize that void **
is not the same as void *, as well.

I realize this may be a gcc-ish question, but perhaps someone has some input.
Feb 5 '07 #27
Christopher Layne wrote:
CBFalconer wrote:
No. What you are guaranteed is that any pointer can be converted
to a void* and back again TO THE ORIGINAL TYPE. You are also
guaranteed that char* and void* have the same representation.
char** is none of these. Neither is int*. Your shortcuts may work
on many machines, but are not guaranteed, and not portable.

This actually brings up a question of mine. I have simple stack code that
consists of the following:

/* code */

typedef struct list_s__ list_s;
struct list_s__ {
list_s *n;
const void *d;
};

extern list_s *ls_push(list_s *lp, const void *d)
{
list_s *lpn;

lpn = ec_malloc(sizeof *lpn);
lpn->n = lp;
lpn->d = d;

return lpn;
}

extern list_s *ls_pop(list_s *lp, void **d)
{
list_s *lpn;

if (lp == NULL) {
if (d) *d = NULL;
return NULL;
}

if (d) *d = (void *)lp->d;
lpn = lp->n;
free(lp);

return lpn;
}

Now the following will always issue a strict aliasing violation w/ gcc if I
cast to void **, rather than void *.

void a(void)
{
list_s *l = NULL;
int *ip, i = 47;

l = ls_push(l, &i);
#ifdef VVP
/* strict aliasing violation, but still "works" */
l = ls_pop(l, (void **)&ip);
#else
/* works, but doesn't feel correct to me */
l = ls_pop(l, (void *)&ip);
#endif
return;
}

$ cc -DVVP -Os -W -Wall -pedantic -g3 -c li.c
li.c: In function 'a':
li.c:11: warning: dereferencing type-punned pointer will break strict-aliasing
rules
$ cc -Os -W -Wall -pedantic -g3 -c li.c
$

Alternatively, I could just change the code to return the data, on pop, rather
than return the head - but it's an idiom I typically use often (checking head
for NULL in a loop construct, basic list stuff, etc). From past google
searches, people have mentioned that casting to void * "fixes" this
diagnostic. My question is "why?" as it expects an argument of void **, and
casting to void * does seem like monkeying around. I do realize that void **
is not the same as void *, as well.
You are correct. As far as GCC is concerned, casting to void * means
"trust me, I know what I'm doing". It will not disable any
optimisations, it will break exactly as much as a direct cast to void
**. It will simply tell GCC not to let you know about it. To fix the
code without changes to the interface, declare ip as void *, and
convert it to int * when you want to use it.

Feb 5 '07 #28
In article <ln************@nuthaus.mib.orgKeith Thompson <ks***@mib.orgwrites:
ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
In article <JC********@cwi.nl>, Dik T. Winter <Di********@cwi.nlwrote:
I don't know what would happen if you set the high-order bits to
non-zero and then attempted to use it as a word pointer, but any
attempt to do so would invoke undefined behavior anyway.
>Within the hardware there is no problem. It uses only 24 or 32
>low-order bits (depending on the model).
This has been true on other architectures, and come back to bite those
who relied on it. Unlikely in this case, admittedly.

In this case, it's the compiler that depends on it, and the compiler
and hardware are provided by the same vendor.
You will find that also utilities tend to depend on such features,
yielding a less portable utility. One of the most difficult to port
culprits I have seen was the Unix Bourne shell and Korn shell. They
used the fact that in a word pointer the low order bit was 0, so that
bit was used for other purposes.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Feb 6 '07 #29
Harald van D?k wrote:
You are correct. As far as GCC is concerned, casting to void * means
"trust me, I know what I'm doing". It will not disable any
optimisations, it will break exactly as much as a direct cast to void
**. It will simply tell GCC not to let you know about it. To fix the
code without changes to the interface, declare ip as void *, and
convert it to int * when you want to use it.
This made me think of something else. Is the following valid and portable?

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

typedef enum { ALLOC = 1 } func_fl;
const char tstr[] = "test string";

int func(void *p, size_t l, func_fl flags)
{
char **q;

if (flags == ALLOC) {
p = *(q = p) = malloc((l = sizeof tstr));
if (p == NULL) abort();
memcpy(p, tstr, l);
}

fprintf(stderr, "f(): l == %ld, p == %.*s\n", (long)l, l, (char *)p);

return l;
}

int main(int argc, char **argv)
{
char *a;
size_t l;
func_fl f;

if (argc <= 2) return EXIT_FAILURE;

f = *argv[1] == '1' ? ALLOC : 0;
a = argv[2];

if (f)
l = func(&a, 0, f);
else
l = func(a, strlen(a), f);

fprintf(stderr, "m(): l == %ld, b == %.*s\n", (long)l, l, a);

if (f) free(a);

return EXIT_SUCCESS;
}

$ cc -O3 -g3 -W -Wall -pedantic -o tf tf.c
$
$ ./tf 0 "dude this seems a bit voodoo"
f(): l == 28, p == dude this seems a bit voodoo
m(): l == 28, b == dude this seems a bit voodoo
$
$ ./tf 1 "dude this seems a bit voodoo"
f(): l == 12, p == test string
m(): l == 12, b == test string

Feb 6 '07 #30
Christopher Layne wrote:
Is the following valid and portable?
p = *(q = p) = malloc((l = sizeof tstr));
No.
Assignment is not a sequence point.
Which of q or p or *q is written to first,
is not defined by the standard.

--
pete
Feb 6 '07 #31
pete wrote:
Christopher Layne wrote:
Is the following valid and portable?
p = *(q = p) = malloc((l = sizeof tstr));

No.
Assignment is not a sequence point.
Which of q or p or *q is written to first,
is not defined by the standard.
It was a long argument a while back. I don't think there ever was a
definitive answer.
- q is only written to. It is never read. The expression (q = p) is
not an lvalue; it has a side effect, but its value is the result of p,
converted to the type of q. There is no problem with q.
- *q is only written to. It is never read. See above. There is no
problem with *q.
- p is only written to once, and only read in the expression that
determines the value to be stored. p = p + 1 would be well-defined.
The big question for this part of the code is whether p itself is
considered read only to determine the value to be stored. Personally,
I don't think so. The value of the complete right-hand side of the
assignment to p depends on *(q = p)'s type (see above), not its value,
so it can be evaluated before *(q = p) is. If that logic is correct,
the code has undefined behaviour. However, q and *q are not relevant
to that.

Feb 6 '07 #32
Christopher Layne wrote:
Harald van D?k wrote:
You are correct. As far as GCC is concerned, casting to void * means
"trust me, I know what I'm doing". It will not disable any
optimisations, it will break exactly as much as a direct cast to void
**. It will simply tell GCC not to let you know about it. To fix the
code without changes to the interface, declare ip as void *, and
convert it to int * when you want to use it.

This made me think of something else. Is the following valid and portable?
[...]
What exactly do you think might be wrong with it?

Feb 6 '07 #33
Harald van D?k wrote:
Christopher Layne wrote:
>Harald van D?k wrote:
You are correct. As far as GCC is concerned, casting to void * means
"trust me, I know what I'm doing". It will not disable any
optimisations, it will break exactly as much as a direct cast to void
**. It will simply tell GCC not to let you know about it. To fix the
code without changes to the interface, declare ip as void *, and
convert it to int * when you want to use it.

This made me think of something else. Is the following valid and portable?
[...]
What exactly do you think might be wrong with it?
Well.. I have doubts about the passing of a char ** through a void * and then
converting it back to a char **. Technically I should not have doubts as this
is supposed to be supported by the standard. But does the standard specify
that one can pass pointers to pointers of type X through (or as a) void *?

Obviously char * -void * and back no issues.
But char *** -void * -char *** and back. Legal, no conversion and/or
alignment issues?
Feb 7 '07 #34
Christopher Layne wrote:
Harald van D?k wrote:
Christopher Layne wrote:
Harald van D?k wrote:
You are correct. As far as GCC is concerned, casting to void * means
"trust me, I know what I'm doing". It will not disable any
optimisations, it will break exactly as much as a direct cast to void
**. It will simply tell GCC not to let you know about it. To fix the
code without changes to the interface, declare ip as void *, and
convert it to int * when you want to use it.

This made me think of something else. Is the following valid and portable?
[...]
What exactly do you think might be wrong with it?

Well.. I have doubts about the passing of a char ** through a void * and then
converting it back to a char **. Technically I should not have doubts as this
is supposed to be supported by the standard. But does the standard specify
that one can pass pointers to pointers of type X through (or as a) void *?

Obviously char * -void * and back no issues.
But char *** -void * -char *** and back. Legal, no conversion and/or
alignment issues?
That's fine. Any pointer to any object type can be converted to void *
and back without loss of information.

Feb 7 '07 #35
background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
Just an info because you are creating IDL compiler which will take in
any valid C code. Apart from from data pointers and arrays functions
pointers can also be given. And sizeof operator should not be used
with function pointers.
i found this in K&R section A.7.4.8

Feb 8 '07 #36
"quarkLore" <ag*************@gmail.comwrites:
>background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
Just an info because you are creating IDL compiler which will take in
any valid C code. Apart from from data pointers and arrays functions
pointers can also be given. And sizeof operator should not be used
with function pointers.
i found this in K&R section A.7.4.8
I don't have a recent edition to check but it seems unlikely that they
are at odds with the C standard. Are you, perhaps, confusing
"function pointers" with an "expression that has function type"?

It is easy to confuse the two, because a function name (which is
simple expressions with function type) is converted to a pointer to
that function *except* when it is the operand of sizeof (or of &).

--
Ben.
Feb 8 '07 #37
On Thu, 08 Feb 2007 11:12:43 +0000, Ben Bacarisse
<be********@bsb.me.ukwrote:
>"quarkLore" <ag*************@gmail.comwrites:
>>background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.
Just an info because you are creating IDL compiler which will take in
any valid C code. Apart from from data pointers and arrays functions
pointers can also be given. And sizeof operator should not be used
with function pointers.
i found this in K&R section A.7.4.8

I don't have a recent edition to check but it seems unlikely that they
are at odds with the C standard. Are you, perhaps, confusing
"function pointers" with an "expression that has function type"?

It is easy to confuse the two, because a function name (which is
simple expressions with function type) is converted to a pointer to
that function *except* when it is the operand of sizeof (or of &).
A function name cannot be the operand of sizeof.
Remove del for email
Feb 9 '07 #38
Barry Schwarz <sc******@doezl.netwrites:
On Thu, 08 Feb 2007 11:12:43 +0000, Ben Bacarisse
<be********@bsb.me.ukwrote:
>>"quarkLore" <ag*************@gmail.comwrites:
>>>background on this: I'm writing a simple IDL compiler that produces 'C'
code, and am trying to get array/pointer marshalling to be 'safe' across
architectures. Any good literature/references on the subject (from a C
perspective) would be appreciated.

Just an info because you are creating IDL compiler which will take in
any valid C code. Apart from from data pointers and arrays functions
pointers can also be given. And sizeof operator should not be used
with function pointers.
i found this in K&R section A.7.4.8

I don't have a recent edition to check but it seems unlikely that they
are at odds with the C standard. Are you, perhaps, confusing
"function pointers" with an "expression that has function type"?

It is easy to confuse the two, because a function name (which is
simple expressions with function type) is converted to a pointer to
that function *except* when it is the operand of sizeof (or of &).

A function name cannot be the operand of sizeof.
No indeed. Nor can any expression that has function type (6.5.3.4.1).

Section 6.3.2.1.4 explains the two cases when a "function designator"
will not get converted to a pointer -- one of these being when it is
the operand of sizeof. Are there *any* cases when you can pass a
function designator to sizeof and not fall foul of 6.5.3.4.1?

I kept the two issues separate (as the standard seems to) just in case!

--
Ben.
Feb 9 '07 #39

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
by: signuts | last post by:
I'm aware of what sizeof(...) does, what I would like to know is if sizeof(...) is compiled in or a function that's executed at run-time. Like for example { int a; printf("a is %d...
79
by: syntax | last post by:
what is the size of a pointer? suppose i am writing, datatype *ptr; sizeof(ptr); now what does this sizeof(ptr) will give? will it give the size of the
33
by: Chris Fogelklou | last post by:
What is wrong with the above? Don't worry, I already know (learned my lesson last week.) It is for the benefit of our resident compiler guru who seems to think you need the cast. I thought it...
9
by: vijay | last post by:
Hello, I am new to C Programming and just started reading K&R. I was about to finish the pointers chapter but got very confused with: 1. int arr; >From what I have read, arr is a pointer to...
6
by: Amigo | last post by:
Hello all! I started working on an embedded project a few ago on Freescale 16-bit micro with an IAR toolset. Running PolySpace for the project code highlighted amongst other things a peculiar...
2
by: GRenard | last post by:
Hello, We just switch in our company to VisualStudio 2005 and the new ATL library. We use a wrapper to use CFileDialog. Its name is CFileDialogDeluxe Here the call CFileDialogDeluxe...
17
by: kevin | last post by:
this is my programm .... char *p="abcde"; char a="abcde"; ..... printf("the size of p is:%d\n",sizeof(p)); printf("the size of a is:%d\n",sizeof(a)); ........
2
by: anon.asdf | last post by:
Hi! Q. 1) How does one write: sizeof(array of 5 "pointers to double") ??? I know that sizeof(pointer to an array of 5 doubles) can be written as: sizeof(double (*));
16
by: Alex Vinokur | last post by:
Does it have to be? : sizeof (size_t) >= sizeof (pointer) Alex Vinokur email: alex DOT vinokur AT gmail DOT com http://mathforum.org/library/view/10978.html http://sourceforge.net/users/alexvn
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.