473,320 Members | 1,828 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,320 software developers and data experts.

mutually referential (Pg 140 K&R2)

Pg. 140 of K&R2 shows an example of mutually referential structure
declarations...

struct t
{
struct s *p;
};

struct s
{
struct t *q;
};
I ran the following test program through my C compiler to see if it
would compile:

#include <stdlib.h>

struct t
{
struct s *p; /* type 'struct s' is not visible here */
};

struct s
{
struct t *q;
};

int main()
{
printf("Hello world\n");
return 0;
}
It compiled and ran without any noticeable problems. I expected it to
complain about the line I've commented above.

How is this valid when the type 'struct s' is not in scope when *p is
declared as a member of the type struct t?

If this is 'valid' please tell me why scopes don't apply here. If this
is 'not valid' please tell me how I can declare mutually referential
struct types.

Thank you

Nov 14 '05 #1
14 1544
G Patel wrote:
Pg. 140 of K&R2 shows an example of mutually referential structure
declarations...

struct t
{
struct s *p;
};

struct s
{
struct t *q;
};
I ran the following test program through my C compiler to see if it
would compile:

#include <stdlib.h>

struct t
{
struct s *p; /* type 'struct s' is not visible here */
};

struct s
{
struct t *q;
};

int main()
{
printf("Hello world\n");
return 0;
}
It compiled and ran without any noticeable problems. I expected it to
complain about the line I've commented above.

How is this valid when the type 'struct s' is not in scope when *p is
declared as a member of the type struct t?

If this is 'valid' please tell me why scopes don't apply here. If this
is 'not valid' please tell me how I can declare mutually referential
struct types.

Thank you


The following code will place both structs in scope. The first "struct
t;" is unnecessary, but it demonstrates the point.

#include <stdio.h>

struct s;
struct t;

struct t {
struct s *p;
};

struct s {
struct t *q;
};

int main(void) {
printf("Hello world\n");
return 0;
}
Nov 14 '05 #2
In article <11**********************@g14g2000cwa.googlegroups .com>
G Patel <ga********@gmail.com> wrote:
Pg. 140 of K&R2 shows an example of mutually referential structure
declarations...
[Vertically compressed]
struct t { struct s *p; };
struct s { struct t *q; };
[snippage]
How is this valid when the type 'struct s' is not in scope when *p is
declared as a member of the type struct t?
Structures -- which are C's general-purpose "create me a new type"
thingy -- can be declared, as well as defined.

The minimal syntax of such a declaration is:

struct tag;

while the minimal syntax of a definition that uses a tag[%] is:

struct tag { FIRST_MEMBER; };

In other words, without the open brace, you are merely mentioning
the *name* of a type, rather than defining that type. (The contents
inside the braces define the type itself.)

[%footnote: New structure types can be left un-named by omitting
the tag. This has relatively limited usefulness since the name
cannot then be repeated. On the other hand, it is possible to
"capture" the un-named type name using C's "typedef" keyword, which
-- despite its name -- does not actually define new types. Instead,
it defines aliases for existing types. If you capture the no-name
type under some alternative alias, you can use the alias. It is
a bit like referring to either Clark Kent as Superman: if Clark
Kent had not had a real name, you would have had to call him Superman
even when he was in disguise. :-) ]

Given a type-name, you can of course declare variables of that
type, and pointers to that type, and so on:

int i; /* this means "i" is an "int" */
char *cp; /* this means *cp is a "char" */

The same holds true for your own types:

struct type1 s1; /* i.e., s1 is a "type1" */
struct type2 *s2; /* i.e., *s2 is a "type2" */

If you have already defined your type, this is fine; if you have
not yet defined your type, it is what C calls an "incomplete type".
You can sometimes, but not always, declare ordinary variables that
have incomplete types; you can always declare pointers to incomplete
types. (More specifically -- and more confusingly -- if T is an
incomplete type, "T *", pointer-to-T, is itself a complete type.
It merely points to an incomplete type.)
If this is 'valid' please tell me why scopes don't apply here.


Scopes can in fact apply here:

struct s { long l; };

void f(void) {
struct s; /* this "vacuous" declaration clears the way */

struct s { char c; } var;
/* this is a new, different type also named s */
...
}

Note, however, that the scope is introduced by the definition of
function f(), not the braces around the structure members. (This
is one area where C and C++ differ: in C++, structure members can
have their own scope, limited to the structure. The C++ rules are
much more complicated than the C rules.)

I realize this is also confusing. I recommend never doing it, in
the same way that I recommend against code like:

int number_of_zorgs;
void f(void) {
int number_of_zorgs;
...
}

Here we have two ordinary "int" variables with the same name. It
becomes confusing if we attempt to talk about both variables at
the same time, since they both have the same name. (Since my own
given name is quite common, I have a lot of personal experience
with this problem. Sometimes I am in a group that has two or three
"Chris"es in it. Sometimes people resort to numbering us.)

With all that out of the way, let us revisit the mutually-referential
structure issue. Given:

struct s; /* declare type s without defining it */
struct t; /* and likewise for type t */

struct s { struct t *tp; }; /* now define s */
struct t { struct s *sp; }; /* and t */

it is easy enough to see that an "s" refers indirectly (via pointer)
to a "t", and a "t" refers indirectly to an "s". We declared both
ahead of time, and then defined both.

C, however, allows us to be sloppy. A type-name simply springs
into existence as soon as we mention it (using C's type-name-creating
keyword "struct", of course). So we do not have to declare the
two types in advance -- we can just start defining one, and declare
the other in the middle of the first one's definition. This is
what you had in your sample code.

There are some problems with this. Typos sneak in, as pointed out
in another thread earlier. If we declare or define a type called
"gargleblaster", it is easy to mis-type the name as "garbleblaster"
(garG => garB) at some point:

struct gargleblaster; /* optionally, insert { contents } here too */
...
extern void somefunc(struct garbleblaster *);

We never declared (much less defined) the misspelled name, so it
simply springs into existence as a new incomplete type. (Some use
this as an argument for using typedefs; and it is a valid argument
for that, despite my own tastes running the other way.)

Structure types *do* obey scopes (despite having none of their
own). In general, incomplete structure types are only usefully
completed in the same scope (it is possible to complete them in an
inner scope, but this has relatively little practical application).
Unfortunately for this particular case, function prototype arguments
have "prototype scope", which ends -- and can never be resurrected
-- at the close parenthesis ending the prototype sequence. Thus
the declaration of function somefunc() declares an incomplete type
("garbleblaster", our misspelled "gargleblaster") that can never
be completed. Better compilers generally produce a warning here.
The warning is, however, confusing until you understand this whole
paragraph.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #3
G Patel wrote:
Pg. 140 of K&R2 shows an example of mutually referential structure
declarations...

struct t
{
struct s *p;
};

struct s
{
struct t *q;
};
I ran the following test program through my C compiler to see if it
would compile:

#include <stdlib.h>

struct t
{
struct s *p; /* type 'struct s' is not visible here */
};

struct s
{
struct t *q;
};

int main()
{
printf("Hello world\n");
return 0;
}
It compiled and ran without any noticeable problems. I expected it to
complain about the line I've commented above.

How is this valid when the type 'struct s' is not in scope when *p is
declared as a member of the type struct t?

If this is 'valid' please tell me why scopes don't apply here. If this
is 'not valid' please tell me how I can declare mutually referential
struct types.


struct s *p declares p using an incomplete struct s type, which is later completed
with struct s {...}. Incomplete types apply only to curly bracket things like
enums, unions, and structs iirc.
Nov 14 '05 #4
On 22 Apr 2005 21:13:49 -0700, "G Patel" <ga********@gmail.com> wrote:
Pg. 140 of K&R2 shows an example of mutually referential structure
declarations...

struct t
{
struct s *p;
};

struct s
{
struct t *q;
};
I ran the following test program through my C compiler to see if it
would compile:

#include <stdlib.h>

struct t
{
struct s *p; /* type 'struct s' is not visible here */
};

struct s
{
struct t *q;
};

int main()
{
printf("Hello world\n");
return 0;
}
It compiled and ran without any noticeable problems. I expected it to
complain about the line I've commented above.

How is this valid when the type 'struct s' is not in scope when *p is
declared as a member of the type struct t?

If this is 'valid' please tell me why scopes don't apply here. If this
is 'not valid' please tell me how I can declare mutually referential
struct types.


The fact that you compiler does not generate a diagnostic has no
bearing on whether the code is valid or not. The opposite is also
true. The compiler is allowed to generate a diagnostic even if the
code is perfectly valid.

Maybe you should raise the warning level on your compiler.

Maybe your compiler is defective in this area.

Maybe it is an extension your compiler provides. Can you disable
extensions?
<<Remove the del for email>>
Nov 14 '05 #5
G Patel wrote:
Pg. 140 of K&R2 shows an example of mutually referential structure
declarations...

struct t
{
struct s *p;
};

struct s
{
struct t *q;
};
I ran the following test program through my C compiler to see if it
would compile:

#include <stdlib.h>

struct t
{
struct s *p; /* type 'struct s' is not visible here */
};

struct s
{
struct t *q;
};

int main()
{
printf("Hello world\n");
return 0;
}
It compiled and ran without any noticeable problems. I expected it to
complain about the line I've commented above.

How is this valid when the type 'struct s' is not in scope when *p is
declared as a member of the type struct t?

If this is 'valid' please tell me why scopes don't apply here. If this
is 'not valid' please tell me how I can declare mutually referential
struct types.

Thank you

What everyone here is trying to say is you should forward-declare the
struct before you use it in this case. See below for an example.

struct s; /* forward-declare the struct we will define later */

struct t
{
struct s *p;
};

struct s
{
struct t *q;
};

The above is an example of the "right way".

Joe Estock
Nov 14 '05 #6
Chris Torek wrote:
Scopes can in fact apply here:

struct s { long l; };

void f(void) {
struct s; /* this "vacuous" declaration clears the way */

struct s { char c; } var;
/* this is a new, different type also named s */
...
}
In this example the vacuous declaration doesn't make any difference;
the inner "full" declaration is valid and declares a type distinct
from the outer declaration regardless. The vacuous declaration is
needed when you want a name in an inner scope to match a tag defined
in the (same) inner scope instead of a tag from the outer scope.

struct f { long l; };

void h(void) {
struct f; /* "vacuous" declaration */

struct g { struct f *p; };
struct f { char p };
}

If the vacuous declaration were omitted `p' would be a pointer to a
struct of the outer "f" type; the vacuous declaration hides the outer
struct declaration and introduces a new type that is completed later
on within the inner scope. Following the vacuous declaration all
references to "struct f" within the block refer to this inner type.

I can't think of a situation where this would actually be useful; it's
always more straightforward to give the inner struct a distinct name.
In general, incomplete structure types are only usefully completed
in the same scope (it is possible to complete them in an inner
scope, but this has relatively little practical application).


I don't think there is a way to complete incomplete structure types in
an inner scope.

Jeremy.
Nov 14 '05 #7
>Chris Torek wrote:
struct s { long l; };
void f(void) {
struct s; /* this "vacuous" declaration clears the way */
struct s { char c; } var;
/* this is a new, different type also named s */
...
}
In article <d4**********@news.e7even.com>
Jeremy Yallop <je****@jdyallop.freeserve.co.uk> wrote:
In this example the vacuous declaration doesn't make any difference;
the inner "full" declaration is valid and declares a type distinct
from the outer declaration regardless. The vacuous declaration is
needed when you want a name in an inner scope to match a tag defined
in the (same) inner scope instead of a tag from the outer scope.
Ah, yes, I believe you are correct.

[snippage]
In general, incomplete structure types are only usefully completed
in the same scope (it is possible to complete them in an inner
scope, but this has relatively little practical application).

I don't think there is a way to complete incomplete structure types in
an inner scope.


This does seem to be the case (i.e., given an incomplete "struct
X" at some outer scope, any attempt to complete it at any nested
scope will instead define a new type of the same name).

To generalize: the vacuous (empty/forward) declarations of struct
tags is often not required, but never actually harmful. It is
required if you are overriding an outer-scope name for mutually
referential structures limited to some inner scope, and it is often
required if you want to have prototype arguments using a type that
will not be defined (i.e., will be left incomplete):

/* interface.h */

struct bob; /* required */

void raise_bob(struct bob *);
void lower_bob(struct bob *);
void move_bob_sideways(struct bob *, int);

but:

/* other_interface.h */

/* struct jane; -- allowed but not required */

struct jane *new_jane(void);
void move_jane_sideways(struct jane *, int);

Here the first mention of the type "jane" occurs outside a prototype,
at the outermost scope, so it springs into being at that point and
the declaration of the function move_jane_sideways() refers to the
existing, incomplete type.

One can either learn all these rules, or just write out the vacuous
declarations. :-)

If you like typedefs, or are commanded :-) to use them, I recommend
writing out all the typedef sequences first:

typedef struct bob BOB;
typedef struct plumb PLUMB;

/* optional: now complete it */
struct bob {
BOB *list_of_bobs;
PLUMB *parent;
... fill this in ...
};

void move_bob_sideways(BOB *, int);

Note that by listing all the types first, and giving them all
their aliases -- you can do this with the "value meal combo deal"
construct above, or by writing it all out:

struct bob;
typedef struct bob BOB;

struct plumb;
typedef struct plumb PLUMB;

-- by giving them their aliases *before* you define them, you
are able to use the aliases inside the definition.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #8
On Fri, 22 Apr 2005 22:36:14 -0700, Barry Schwarz wrote:
On 22 Apr 2005 21:13:49 -0700, "G Patel" <ga********@gmail.com> wrote:


....
I ran the following test program through my C compiler to see if it
would compile:

#include <stdlib.h>
You don't need <stdlib.h> for this code but you do need to #include
<stdio.h> since the code uses printf().
struct t
{
struct s *p; /* type 'struct s' is not visible here */
};

struct s
{
struct t *q;
};

int main()
{
printf("Hello world\n");
return 0;
}
It compiled and ran without any noticeable problems. I expected it to
complain about the line I've commented above.

How is this valid when the type 'struct s' is not in scope when *p is
declared as a member of the type struct t?

If this is 'valid' please tell me why scopes don't apply here. If this
is 'not valid' please tell me how I can declare mutually referential
struct types.


The fact that you compiler does not generate a diagnostic has no
bearing on whether the code is valid or not. The opposite is also
true. The compiler is allowed to generate a diagnostic even if the
code is perfectly valid.

Maybe you should raise the warning level on your compiler.

Maybe your compiler is defective in this area.


If we add #include <stdio.h> the code is perfectly valid. I don't see any
defect in the area under discussion.

Lawrence
Nov 14 '05 #9
Joe Estock wrote:
G Patel wrote:
It compiled and ran without any noticeable problems.
I expected it to complain
What everyone here is trying to say is you should forward-declare
the struct before you use it in this case.


What? You shouldn't forward-declare the struct, and the
original code is perfectly fine.
struct s; /* forward-declare the struct we will define later */
This line achieves nothing; the struct is automatically
forward-declared the first time it is used, in this example.
struct t { struct s *p; };
struct s { struct t *q; };

The above is an example of the "right way".


The right way to write redundant code?

Nov 14 '05 #10
G Patel wrote:

Pg. 140 of K&R2 shows an example of mutually referential structure
declarations...

struct t
{
struct s *p;
};

struct s
{
struct t *q;
};
I ran the following test program through my C compiler to see if it
would compile:

#include <stdlib.h>

struct t
{
struct s *p; /* type 'struct s' is not visible here */
};

struct s
{
struct t *q;
};

int main()
{
printf("Hello world\n");
return 0;
}

It compiled and ran without any noticeable problems. I expected
it to complain about the line I've commented above.

How is this valid when the type 'struct s' is not in scope when *p
is declared as a member of the type struct t?

If this is 'valid' please tell me why scopes don't apply here. If
this is 'not valid' please tell me how I can declare mutually
referential struct types.


To form those declared structures the compiler only needs to know
the size of a pointer to a structure. In order to allow for
mutually recursive data definitions of this sort, the C standard
has a provision that states that all pointers to structures shall
be the same size. However if you try to dereference that pointer
before properly completing the definition, there will be errors.
Meanwhile the compiler knows how much space to allocate for the
pointer, and can carry on.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #11
On Sat, 23 Apr 2005 15:23:02 +1000, Russell Shaw
<rjshawN_o@s_pam.netspace.net.au> wrote:
<snip>
struct s *p declares p using an incomplete struct s type, which is later completed
with struct s {...}.
Correct.
Incomplete types apply only to curly bracket things like
enums, unions, and structs iirc.


YDNRC.

Forward declared struct and union tags are incomplete, until (the end
of) the full definition (if any). You can't forward declare an enum
tag; technically an enum type is incomplete from its type-specifier to
its closing brace, but this only means you can't use sizeof(enum foo)
as one of its own values which seems pretty silly anyway.

Array with unspecified bound is an incomplete type, which can be used
to access an actual array defined elsewhere, which definition requires
a bound and linkage requires static duration; or when used as a
Flexible Array Member at the end of a struct in C99 can be used to
access actual memory of varying sizes.

'void' is an incomplete type that cannot be completed.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #12
Dave Thompson wrote:

On Sat, 23 Apr 2005 15:23:02 +1000, Russell Shaw
<rjshawN_o@s_pam.netspace.net.au> wrote:
<snip>
struct s *p declares p using an incomplete struct s type, which is later completed
with struct s {...}.


Correct.
Incomplete types apply only to curly bracket things like
enums, unions, and structs iirc.


YDNRC.

Forward declared struct and union tags are incomplete, until (the end
of) the full definition (if any). You can't forward declare an enum
tag; technically an enum type is incomplete from its type-specifier to
its closing brace, but this only means you can't use sizeof(enum foo)
as one of its own values which seems pretty silly anyway.


I think you can. The enum type is complete,
that is to say that it's type size is known at compile time,
even if it's values haven't been specified.

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
enum foo {Zero = sizeof (enum foo), One};
enum bar;

printf("sizeof (enum bar) is %lu bytes\n.",
(long unsigned)sizeof(enum bar));
return One - Zero - 1;
}

/* END new.c */
--
pete
Nov 14 '05 #13
pete <pf*****@mindspring.com> writes:
Dave Thompson wrote:

[...]
Forward declared struct and union tags are incomplete, until (the end
of) the full definition (if any). You can't forward declare an enum
tag; technically an enum type is incomplete from its type-specifier to
its closing brace, but this only means you can't use sizeof(enum foo)
as one of its own values which seems pretty silly anyway.


I think you can. The enum type is complete,
that is to say that it's type size is known at compile time,
even if it's values haven't been specified.

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
enum foo {Zero = sizeof (enum foo), One};
enum bar;

printf("sizeof (enum bar) is %lu bytes\n.",
(long unsigned)sizeof(enum bar));
return One - Zero - 1;
}

/* END new.c */


No. C99 6.7.2.2p4 says:

Each enumerated type shall be compatible with char, a signed
integer type, or an unsigned integer type. The choice of type is
implementation-defined, but shall be capable of representing
the values of all the members of the enumeration. The enumerated
type is incomplete until after the } that terminates the list of
enumerator declarations.

A footnote says:

An implementation may delay the choice of which integer type until
all enumeration constants have been seen.

If your compiler accepts the above code (in conforming mode), it's
probably broken. <OT>gcc doesn't.</OT>

--
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.
Nov 14 '05 #14
Keith Thompson wrote:

pete <pf*****@mindspring.com> writes:
Dave Thompson wrote:

[...]
Forward declared struct and union tags are incomplete, until (the end
of) the full definition (if any). You can't forward declare an enum
tag; technically an enum type is incomplete from its type-specifier to
its closing brace, but this only means you can't use sizeof(enum foo)
as one of its own values which seems pretty silly anyway.


I think you can. The enum type is complete,
that is to say that it's type size is known at compile time,
even if it's values haven't been specified.

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
enum foo {Zero = sizeof (enum foo), One};
enum bar;

printf("sizeof (enum bar) is %lu bytes\n.",
(long unsigned)sizeof(enum bar));
return One - Zero - 1;
}

/* END new.c */


No. C99 6.7.2.2p4 says:

Each enumerated type shall be compatible with char, a signed
integer type, or an unsigned integer type. The choice of type is
implementation-defined, but shall be capable of representing
the values of all the members of the enumeration. The enumerated
type is incomplete until after the } that terminates the list of
enumerator declarations.

A footnote says:

An implementation may delay the choice of which integer type until
all enumeration constants have been seen.

If your compiler accepts the above code (in conforming mode), it's
probably broken. <OT>gcc doesn't.</OT>


It's always distressing to learn something about C,
but that's why I'm here.
Thank you.

--
pete
Nov 14 '05 #15

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

Similar topics

9
by: Anthony Heading | last post by:
Hi all, I've often found myself wanting to write code like the example here. Since both MSVC and gcc both reject it, I suspect it is indeed illegal. gcc: no type named `Name' in `class...
5
by: Colin JN Breame | last post by:
Say there are two classes: class A { B *b; }; class B { A *a; };
8
by: J Krugman | last post by:
My compiler complains if I do something like this typedef struct { node *next; } node; but it's OK with typedef struct superfluous_identifier { superfluous_identifier *next;
1
by: Grant McLean | last post by:
Hi First a simple question ... I have a table "access_log" that has foreign keys "app_id" and "app_user_id" that reference the "application_type" and "app_user" tables. When I insert into...
7
by: Jimmie H. Apsey | last post by:
Referential Integrity on one of our production tables seems to have been lost. I am running Postgres 7.1.3 embedded within Red Hat kernel-2.4.9-e.49. Within that I have a table with referential...
5
by: Geisler, Jim | last post by:
So, as far as I know, PostgreSQL does not have any way of verifying the loss of referential integrity. Are there any recommended methods or utilities for checking referential integrity in a...
6
by: heyvinay | last post by:
I have transaction table where the rows entered into the transaction can come a result of changes that take place if four different tables. So the situation is as follows: Transaction Table...
80
by: Andrew R | last post by:
Hi I'm creating a series of forms, each with with around 15-20 text boxes. The text boxes will show data from tables, but are unbound to make them more flexible. I want the form to be used...
2
by: ApexData | last post by:
Access2000, using a continuous form. I’m getting a message that say “you cannot add or change a record because a related record is required in table Employee”. This occurs in all my combobox...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.